5 "github.com/stretchr/testify/assert"
6 "github.com/stretchr/testify/mock"
17 func TestHandleSetChatSubject(t *testing.T) {
28 name: "sends chat subject to private chat members",
31 UserName: []byte{0x00, 0x01},
33 PrivateChats: map[[4]byte]*PrivateChat{
34 [4]byte{0, 0, 0, 1}: {
36 ClientConn: map[[2]byte]*ClientConn{
39 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
45 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
52 Clients: map[[2]byte]*ClientConn{
55 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
61 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
69 Type: [2]byte{0, 0x6a},
70 ID: [4]byte{0, 0, 0, 1},
72 NewField(FieldChatID, []byte{0, 0, 0, 1}),
73 NewField(FieldChatSubject, []byte("Test Subject")),
79 clientID: [2]byte{0, 1},
80 Type: [2]byte{0, 0x77},
82 NewField(FieldChatID, []byte{0, 0, 0, 1}),
83 NewField(FieldChatSubject, []byte("Test Subject")),
87 clientID: [2]byte{0, 2},
88 Type: [2]byte{0, 0x77},
90 NewField(FieldChatID, []byte{0, 0, 0, 1}),
91 NewField(FieldChatSubject, []byte("Test Subject")),
97 for _, tt := range tests {
98 t.Run(tt.name, func(t *testing.T) {
99 got := HandleSetChatSubject(tt.args.cc, &tt.args.t)
100 if !tranAssertEqual(t, tt.want, got) {
101 t.Errorf("HandleSetChatSubject() got = %v, want %v", got, tt.want)
107 func TestHandleLeaveChat(t *testing.T) {
118 name: "returns expected transactions",
123 PrivateChats: map[[4]byte]*PrivateChat{
124 [4]byte{0, 0, 0, 1}: {
125 ClientConn: map[[2]byte]*ClientConn{
128 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
134 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
141 Clients: map[[2]byte]*ClientConn{
144 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
150 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
157 t: NewTransaction(TranDeleteUser, [2]byte{}, NewField(FieldChatID, []byte{0, 0, 0, 1})),
161 clientID: [2]byte{0, 1},
162 Type: [2]byte{0, 0x76},
164 NewField(FieldChatID, []byte{0, 0, 0, 1}),
165 NewField(FieldUserID, []byte{0, 2}),
171 for _, tt := range tests {
172 t.Run(tt.name, func(t *testing.T) {
173 got := HandleLeaveChat(tt.args.cc, &tt.args.t)
174 if !tranAssertEqual(t, tt.want, got) {
175 t.Errorf("HandleLeaveChat() got = %v, want %v", got, tt.want)
181 func TestHandleGetUserNameList(t *testing.T) {
192 name: "replies with userlist transaction",
197 Clients: map[[2]byte]*ClientConn{
201 Flags: [2]byte{0, 3},
202 UserName: []byte{0, 4},
207 Flags: [2]byte{0, 3},
208 UserName: []byte{0, 4},
217 clientID: [2]byte{0, 1},
221 FieldUsernameWithInfo,
222 []byte{00, 01, 00, 02, 00, 03, 00, 02, 00, 04},
225 FieldUsernameWithInfo,
226 []byte{00, 02, 00, 02, 00, 03, 00, 02, 00, 04},
233 for _, tt := range tests {
234 t.Run(tt.name, func(t *testing.T) {
235 got := HandleGetUserNameList(tt.args.cc, &tt.args.t)
236 assert.Equal(t, tt.want, got)
241 func TestHandleChatSend(t *testing.T) {
252 name: "sends chat msg transaction to all clients",
256 Access: func() accessBitmap {
257 var bits accessBitmap
258 bits.Set(accessSendChat)
262 UserName: []byte{0x00, 0x01},
264 Clients: map[[2]byte]*ClientConn{
267 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
273 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
282 NewField(FieldData, []byte("hai")),
288 clientID: [2]byte{0, 1},
291 Type: [2]byte{0, 0x6a},
293 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
297 clientID: [2]byte{0, 2},
300 Type: [2]byte{0, 0x6a},
302 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
308 name: "treats Chat ID 00 00 00 00 as a public chat message",
312 Access: func() accessBitmap {
313 var bits accessBitmap
314 bits.Set(accessSendChat)
318 UserName: []byte{0x00, 0x01},
320 Clients: map[[2]byte]*ClientConn{
323 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
329 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
338 NewField(FieldData, []byte("hai")),
339 NewField(FieldChatID, []byte{0, 0, 0, 0}),
345 clientID: [2]byte{0, 1},
346 Type: [2]byte{0, 0x6a},
348 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
352 clientID: [2]byte{0, 2},
353 Type: [2]byte{0, 0x6a},
355 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
361 name: "when user does not have required permission",
365 Access: func() accessBitmap {
366 var bits accessBitmap
371 Accounts: map[string]*Account{},
375 TranChatSend, [2]byte{0, 1},
376 NewField(FieldData, []byte("hai")),
382 ErrorCode: [4]byte{0, 0, 0, 1},
384 NewField(FieldError, []byte("You are not allowed to participate in chat.")),
390 name: "sends chat msg as emote if FieldChatOptions is set to 1",
394 Access: func() accessBitmap {
395 var bits accessBitmap
396 bits.Set(accessSendChat)
400 UserName: []byte("Testy McTest"),
402 Clients: map[[2]byte]*ClientConn{
405 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
411 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
420 NewField(FieldData, []byte("performed action")),
421 NewField(FieldChatOptions, []byte{0x00, 0x01}),
427 clientID: [2]byte{0, 1},
430 Type: [2]byte{0, 0x6a},
432 NewField(FieldData, []byte("\r*** Testy McTest performed action")),
436 clientID: [2]byte{0, 2},
439 Type: [2]byte{0, 0x6a},
441 NewField(FieldData, []byte("\r*** Testy McTest performed action")),
447 name: "does not send chat msg as emote if FieldChatOptions is set to 0",
451 Access: func() accessBitmap {
452 var bits accessBitmap
453 bits.Set(accessSendChat)
457 UserName: []byte("Testy McTest"),
459 Clients: map[[2]byte]*ClientConn{
462 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
468 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
477 NewField(FieldData, []byte("hello")),
478 NewField(FieldChatOptions, []byte{0x00, 0x00}),
484 clientID: [2]byte{0, 1},
485 Type: [2]byte{0, 0x6a},
487 NewField(FieldData, []byte("\r Testy McTest: hello")),
491 clientID: [2]byte{0, 2},
492 Type: [2]byte{0, 0x6a},
494 NewField(FieldData, []byte("\r Testy McTest: hello")),
500 name: "only sends chat msg to clients with accessReadChat permission",
504 Access: func() accessBitmap {
505 var bits accessBitmap
506 bits.Set(accessSendChat)
510 UserName: []byte{0x00, 0x01},
512 Clients: map[[2]byte]*ClientConn{
515 Access: func() accessBitmap {
516 var bits accessBitmap
517 bits.Set(accessReadChat)
524 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
533 NewField(FieldData, []byte("hai")),
539 clientID: [2]byte{0, 1},
540 Type: [2]byte{0, 0x6a},
542 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
548 name: "only sends private chat msg to members of private chat",
552 Access: func() accessBitmap {
553 var bits accessBitmap
554 bits.Set(accessSendChat)
558 UserName: []byte{0x00, 0x01},
560 PrivateChats: map[[4]byte]*PrivateChat{
561 [4]byte{0, 0, 0, 1}: {
562 ClientConn: map[[2]byte]*ClientConn{
572 Clients: map[[2]byte]*ClientConn{
575 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
581 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
587 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
596 NewField(FieldData, []byte("hai")),
597 NewField(FieldChatID, []byte{0, 0, 0, 1}),
603 clientID: [2]byte{0, 1},
604 Type: [2]byte{0, 0x6a},
606 NewField(FieldChatID, []byte{0, 0, 0, 1}),
607 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
611 clientID: [2]byte{0, 2},
612 Type: [2]byte{0, 0x6a},
614 NewField(FieldChatID, []byte{0, 0, 0, 1}),
615 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
621 for _, tt := range tests {
622 t.Run(tt.name, func(t *testing.T) {
623 got := HandleChatSend(tt.args.cc, &tt.args.t)
624 tranAssertEqual(t, tt.want, got)
629 func TestHandleGetFileInfo(t *testing.T) {
637 wantRes []Transaction
640 name: "returns expected fields when a valid file is requested",
643 ID: [2]byte{0x00, 0x01},
647 FileRoot: func() string {
648 path, _ := os.Getwd()
649 return filepath.Join(path, "/test/config/Files")
655 TranGetFileInfo, [2]byte{},
656 NewField(FieldFileName, []byte("testfile.txt")),
657 NewField(FieldFilePath, []byte{0x00, 0x00}),
660 wantRes: []Transaction{
662 clientID: [2]byte{0, 1},
666 NewField(FieldFileName, []byte("testfile.txt")),
667 NewField(FieldFileTypeString, []byte("Text File")),
668 NewField(FieldFileCreatorString, []byte("ttxt")),
669 NewField(FieldFileType, []byte("TEXT")),
670 NewField(FieldFileCreateDate, make([]byte, 8)),
671 NewField(FieldFileModifyDate, make([]byte, 8)),
672 NewField(FieldFileSize, []byte{0x0, 0x0, 0x0, 0x17}),
678 for _, tt := range tests {
679 t.Run(tt.name, func(t *testing.T) {
680 gotRes := HandleGetFileInfo(tt.args.cc, &tt.args.t)
682 // Clear the file timestamp fields to work around problems running the tests in multiple timezones
683 // TODO: revisit how to test this by mocking the stat calls
684 gotRes[0].Fields[4].Data = make([]byte, 8)
685 gotRes[0].Fields[5].Data = make([]byte, 8)
687 if !tranAssertEqual(t, tt.wantRes, gotRes) {
688 t.Errorf("HandleGetFileInfo() gotRes = %v, want %v", gotRes, tt.wantRes)
694 func TestHandleNewFolder(t *testing.T) {
702 wantRes []Transaction
705 name: "without required permission",
709 Access: func() accessBitmap {
710 var bits accessBitmap
720 wantRes: []Transaction{
723 ErrorCode: [4]byte{0, 0, 0, 1},
725 NewField(FieldError, []byte("You are not allowed to create folders.")),
731 name: "when path is nested",
735 Access: func() accessBitmap {
736 var bits accessBitmap
737 bits.Set(accessCreateFolder)
746 FS: func() *MockFileStore {
747 mfs := &MockFileStore{}
748 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
749 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
755 TranNewFolder, [2]byte{0, 1},
756 NewField(FieldFileName, []byte("testFolder")),
757 NewField(FieldFilePath, []byte{
765 wantRes: []Transaction{
767 clientID: [2]byte{0, 1},
773 name: "when path is not nested",
777 Access: func() accessBitmap {
778 var bits accessBitmap
779 bits.Set(accessCreateFolder)
788 FS: func() *MockFileStore {
789 mfs := &MockFileStore{}
790 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
791 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
797 TranNewFolder, [2]byte{0, 1},
798 NewField(FieldFileName, []byte("testFolder")),
801 wantRes: []Transaction{
803 clientID: [2]byte{0, 1},
809 name: "when Write returns an err",
813 Access: func() accessBitmap {
814 var bits accessBitmap
815 bits.Set(accessCreateFolder)
824 FS: func() *MockFileStore {
825 mfs := &MockFileStore{}
826 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
827 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
833 TranNewFolder, [2]byte{0, 1},
834 NewField(FieldFileName, []byte("testFolder")),
835 NewField(FieldFilePath, []byte{
840 wantRes: []Transaction{},
843 name: "FieldFileName does not allow directory traversal",
847 Access: func() accessBitmap {
848 var bits accessBitmap
849 bits.Set(accessCreateFolder)
858 FS: func() *MockFileStore {
859 mfs := &MockFileStore{}
860 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
861 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
867 TranNewFolder, [2]byte{0, 1},
868 NewField(FieldFileName, []byte("../../testFolder")),
871 wantRes: []Transaction{
873 clientID: [2]byte{0, 1},
879 name: "FieldFilePath does not allow directory traversal",
883 Access: func() accessBitmap {
884 var bits accessBitmap
885 bits.Set(accessCreateFolder)
894 FS: func() *MockFileStore {
895 mfs := &MockFileStore{}
896 mfs.On("Mkdir", "/Files/foo/testFolder", fs.FileMode(0777)).Return(nil)
897 mfs.On("Stat", "/Files/foo/testFolder").Return(nil, os.ErrNotExist)
903 TranNewFolder, [2]byte{0, 1},
904 NewField(FieldFileName, []byte("testFolder")),
905 NewField(FieldFilePath, []byte{
916 wantRes: []Transaction{
918 clientID: [2]byte{0, 1},
924 for _, tt := range tests {
925 t.Run(tt.name, func(t *testing.T) {
926 gotRes := HandleNewFolder(tt.args.cc, &tt.args.t)
928 if !tranAssertEqual(t, tt.wantRes, gotRes) {
929 t.Errorf("HandleNewFolder() gotRes = %v, want %v", gotRes, tt.wantRes)
935 func TestHandleUploadFile(t *testing.T) {
943 wantRes []Transaction
946 name: "when request is valid and user has Upload Anywhere permission",
951 fileTransfers: map[[4]byte]*FileTransfer{},
953 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
955 transfers: map[int]map[[4]byte]*FileTransfer{
959 Access: func() accessBitmap {
960 var bits accessBitmap
961 bits.Set(accessUploadFile)
962 bits.Set(accessUploadAnywhere)
968 TranUploadFile, [2]byte{0, 1},
969 NewField(FieldFileName, []byte("testFile")),
970 NewField(FieldFilePath, []byte{
978 wantRes: []Transaction{
982 NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}), // rand.Seed(1)
988 name: "when user does not have required access",
992 Access: func() accessBitmap {
993 var bits accessBitmap
999 TranUploadFile, [2]byte{0, 1},
1000 NewField(FieldFileName, []byte("testFile")),
1001 NewField(FieldFilePath, []byte{
1009 wantRes: []Transaction{
1012 ErrorCode: [4]byte{0, 0, 0, 1},
1014 NewField(FieldError, []byte("You are not allowed to upload files.")), // rand.Seed(1)
1020 for _, tt := range tests {
1021 t.Run(tt.name, func(t *testing.T) {
1022 gotRes := HandleUploadFile(tt.args.cc, &tt.args.t)
1023 tranAssertEqual(t, tt.wantRes, gotRes)
1028 func TestHandleMakeAlias(t *testing.T) {
1036 wantRes []Transaction
1039 name: "with valid input and required permissions",
1042 logger: NewTestLogger(),
1044 Access: func() accessBitmap {
1045 var bits accessBitmap
1046 bits.Set(accessMakeAlias)
1052 FileRoot: func() string {
1053 path, _ := os.Getwd()
1054 return path + "/test/config/Files"
1057 Logger: NewTestLogger(),
1058 FS: func() *MockFileStore {
1059 mfs := &MockFileStore{}
1060 path, _ := os.Getwd()
1063 path+"/test/config/Files/foo/testFile",
1064 path+"/test/config/Files/bar/testFile",
1071 TranMakeFileAlias, [2]byte{0, 1},
1072 NewField(FieldFileName, []byte("testFile")),
1073 NewField(FieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1074 NewField(FieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1077 wantRes: []Transaction{
1080 Fields: []Field(nil),
1085 name: "when symlink returns an error",
1088 logger: NewTestLogger(),
1090 Access: func() accessBitmap {
1091 var bits accessBitmap
1092 bits.Set(accessMakeAlias)
1098 FileRoot: func() string {
1099 path, _ := os.Getwd()
1100 return path + "/test/config/Files"
1103 Logger: NewTestLogger(),
1104 FS: func() *MockFileStore {
1105 mfs := &MockFileStore{}
1106 path, _ := os.Getwd()
1109 path+"/test/config/Files/foo/testFile",
1110 path+"/test/config/Files/bar/testFile",
1111 ).Return(errors.New("ohno"))
1117 TranMakeFileAlias, [2]byte{0, 1},
1118 NewField(FieldFileName, []byte("testFile")),
1119 NewField(FieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1120 NewField(FieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1123 wantRes: []Transaction{
1126 ErrorCode: [4]byte{0, 0, 0, 1},
1128 NewField(FieldError, []byte("Error creating alias")),
1134 name: "when user does not have required permission",
1137 logger: NewTestLogger(),
1139 Access: func() accessBitmap {
1140 var bits accessBitmap
1146 FileRoot: func() string {
1147 path, _ := os.Getwd()
1148 return path + "/test/config/Files"
1154 TranMakeFileAlias, [2]byte{0, 1},
1155 NewField(FieldFileName, []byte("testFile")),
1156 NewField(FieldFilePath, []byte{
1162 NewField(FieldFileNewPath, []byte{
1170 wantRes: []Transaction{
1173 ErrorCode: [4]byte{0, 0, 0, 1},
1175 NewField(FieldError, []byte("You are not allowed to make aliases.")),
1181 for _, tt := range tests {
1182 t.Run(tt.name, func(t *testing.T) {
1183 gotRes := HandleMakeAlias(tt.args.cc, &tt.args.t)
1184 tranAssertEqual(t, tt.wantRes, gotRes)
1189 func TestHandleGetUser(t *testing.T) {
1197 wantRes []Transaction
1200 name: "when account is valid",
1204 Access: func() accessBitmap {
1205 var bits accessBitmap
1206 bits.Set(accessOpenUser)
1211 Accounts: map[string]*Account{
1215 Password: "password",
1216 Access: accessBitmap{},
1222 TranGetUser, [2]byte{0, 1},
1223 NewField(FieldUserLogin, []byte("guest")),
1226 wantRes: []Transaction{
1230 NewField(FieldUserName, []byte("Guest")),
1231 NewField(FieldUserLogin, encodeString([]byte("guest"))),
1232 NewField(FieldUserPassword, []byte("password")),
1233 NewField(FieldUserAccess, []byte{0, 0, 0, 0, 0, 0, 0, 0}),
1239 name: "when user does not have required permission",
1243 Access: func() accessBitmap {
1244 var bits accessBitmap
1249 Accounts: map[string]*Account{},
1253 TranGetUser, [2]byte{0, 1},
1254 NewField(FieldUserLogin, []byte("nonExistentUser")),
1257 wantRes: []Transaction{
1260 ErrorCode: [4]byte{0, 0, 0, 1},
1262 NewField(FieldError, []byte("You are not allowed to view accounts.")),
1268 name: "when account does not exist",
1272 Access: func() accessBitmap {
1273 var bits accessBitmap
1274 bits.Set(accessOpenUser)
1279 Accounts: map[string]*Account{},
1283 TranGetUser, [2]byte{0, 1},
1284 NewField(FieldUserLogin, []byte("nonExistentUser")),
1287 wantRes: []Transaction{
1291 Type: [2]byte{0, 0},
1292 ErrorCode: [4]byte{0, 0, 0, 1},
1294 NewField(FieldError, []byte("Account does not exist.")),
1300 for _, tt := range tests {
1301 t.Run(tt.name, func(t *testing.T) {
1302 gotRes := HandleGetUser(tt.args.cc, &tt.args.t)
1303 tranAssertEqual(t, tt.wantRes, gotRes)
1308 func TestHandleDeleteUser(t *testing.T) {
1316 wantRes []Transaction
1319 name: "when user dataFile",
1323 Access: func() accessBitmap {
1324 var bits accessBitmap
1325 bits.Set(accessDeleteUser)
1330 Accounts: map[string]*Account{
1333 Name: "Testy McTest",
1334 Password: "password",
1335 Access: accessBitmap{},
1338 FS: func() *MockFileStore {
1339 mfs := &MockFileStore{}
1340 mfs.On("Remove", "Users/testuser.yaml").Return(nil)
1346 TranDeleteUser, [2]byte{0, 1},
1347 NewField(FieldUserLogin, encodeString([]byte("testuser"))),
1350 wantRes: []Transaction{
1354 Type: [2]byte{0, 0},
1355 Fields: []Field(nil),
1360 name: "when user does not have required permission",
1364 Access: func() accessBitmap {
1365 var bits accessBitmap
1370 Accounts: map[string]*Account{},
1374 TranDeleteUser, [2]byte{0, 1},
1375 NewField(FieldUserLogin, encodeString([]byte("testuser"))),
1378 wantRes: []Transaction{
1381 ErrorCode: [4]byte{0, 0, 0, 1},
1383 NewField(FieldError, []byte("You are not allowed to delete accounts.")),
1389 for _, tt := range tests {
1390 t.Run(tt.name, func(t *testing.T) {
1391 gotRes := HandleDeleteUser(tt.args.cc, &tt.args.t)
1392 tranAssertEqual(t, tt.wantRes, gotRes)
1397 func TestHandleGetMsgs(t *testing.T) {
1405 wantRes []Transaction
1408 name: "returns news data",
1412 Access: func() accessBitmap {
1413 var bits accessBitmap
1414 bits.Set(accessNewsReadArt)
1419 FlatNews: []byte("TEST"),
1423 TranGetMsgs, [2]byte{0, 1},
1426 wantRes: []Transaction{
1430 NewField(FieldData, []byte("TEST")),
1436 name: "when user does not have required permission",
1440 Access: func() accessBitmap {
1441 var bits accessBitmap
1446 Accounts: map[string]*Account{},
1450 TranGetMsgs, [2]byte{0, 1},
1453 wantRes: []Transaction{
1456 ErrorCode: [4]byte{0, 0, 0, 1},
1458 NewField(FieldError, []byte("You are not allowed to read news.")),
1464 for _, tt := range tests {
1465 t.Run(tt.name, func(t *testing.T) {
1466 gotRes := HandleGetMsgs(tt.args.cc, &tt.args.t)
1467 tranAssertEqual(t, tt.wantRes, gotRes)
1472 func TestHandleNewUser(t *testing.T) {
1480 wantRes []Transaction
1483 name: "when user does not have required permission",
1487 Access: func() accessBitmap {
1488 var bits accessBitmap
1493 Accounts: map[string]*Account{},
1497 TranNewUser, [2]byte{0, 1},
1500 wantRes: []Transaction{
1503 ErrorCode: [4]byte{0, 0, 0, 1},
1505 NewField(FieldError, []byte("You are not allowed to create new accounts.")),
1511 name: "when user attempts to create account with greater access",
1515 Access: func() accessBitmap {
1516 var bits accessBitmap
1517 bits.Set(accessCreateUser)
1522 Accounts: map[string]*Account{},
1526 TranNewUser, [2]byte{0, 1},
1527 NewField(FieldUserLogin, []byte("userB")),
1531 var bits accessBitmap
1532 bits.Set(accessDisconUser)
1538 wantRes: []Transaction{
1541 ErrorCode: [4]byte{0, 0, 0, 1},
1543 NewField(FieldError, []byte("Cannot create account with more access than yourself.")),
1549 for _, tt := range tests {
1550 t.Run(tt.name, func(t *testing.T) {
1551 gotRes := HandleNewUser(tt.args.cc, &tt.args.t)
1552 tranAssertEqual(t, tt.wantRes, gotRes)
1557 func TestHandleListUsers(t *testing.T) {
1565 wantRes []Transaction
1568 name: "when user does not have required permission",
1572 Access: func() accessBitmap {
1573 var bits accessBitmap
1578 Accounts: map[string]*Account{},
1582 TranNewUser, [2]byte{0, 1},
1585 wantRes: []Transaction{
1588 ErrorCode: [4]byte{0, 0, 0, 1},
1590 NewField(FieldError, []byte("You are not allowed to view accounts.")),
1596 name: "when user has required permission",
1600 Access: func() accessBitmap {
1601 var bits accessBitmap
1602 bits.Set(accessOpenUser)
1607 Accounts: map[string]*Account{
1612 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
1618 TranGetClientInfoText, [2]byte{0, 1},
1619 NewField(FieldUserID, []byte{0, 1}),
1622 wantRes: []Transaction{
1626 NewField(FieldData, []byte{
1627 0x00, 0x04, 0x00, 0x66, 0x00, 0x05, 0x67, 0x75, 0x65, 0x73, 0x74, 0x00, 0x69, 0x00, 0x05, 0x98,
1628 0x8a, 0x9a, 0x8c, 0x8b, 0x00, 0x6e, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1629 0x00, 0x6a, 0x00, 0x01, 0x78,
1636 for _, tt := range tests {
1637 t.Run(tt.name, func(t *testing.T) {
1638 gotRes := HandleListUsers(tt.args.cc, &tt.args.t)
1640 tranAssertEqual(t, tt.wantRes, gotRes)
1645 func TestHandleDownloadFile(t *testing.T) {
1653 wantRes []Transaction
1656 name: "when user does not have required permission",
1660 Access: func() accessBitmap {
1661 var bits accessBitmap
1667 t: NewTransaction(TranDownloadFile, [2]byte{0, 1}),
1669 wantRes: []Transaction{
1672 ErrorCode: [4]byte{0, 0, 0, 1},
1674 NewField(FieldError, []byte("You are not allowed to download files.")),
1680 name: "with a valid file",
1683 transfers: map[int]map[[4]byte]*FileTransfer{
1687 Access: func() accessBitmap {
1688 var bits accessBitmap
1689 bits.Set(accessDownloadFile)
1695 fileTransfers: map[[4]byte]*FileTransfer{},
1697 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1699 Accounts: map[string]*Account{},
1705 NewField(FieldFileName, []byte("testfile.txt")),
1706 NewField(FieldFilePath, []byte{0x0, 0x00}),
1709 wantRes: []Transaction{
1713 NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1714 NewField(FieldWaitingCount, []byte{0x00, 0x00}),
1715 NewField(FieldTransferSize, []byte{0x00, 0x00, 0x00, 0xa5}),
1716 NewField(FieldFileSize, []byte{0x00, 0x00, 0x00, 0x17}),
1722 name: "when client requests to resume 1k test file at offset 256",
1725 transfers: map[int]map[[4]byte]*FileTransfer{
1727 }, Account: &Account{
1728 Access: func() accessBitmap {
1729 var bits accessBitmap
1730 bits.Set(accessDownloadFile)
1737 // FS: func() *MockFileStore {
1738 // path, _ := os.Getwd()
1739 // testFile, err := os.Open(path + "/test/config/Files/testfile-1k")
1744 // mfi := &MockFileInfo{}
1745 // mfi.On("Mode").Return(fs.FileMode(0))
1746 // mfs := &MockFileStore{}
1747 // mfs.On("Stat", "/fakeRoot/Files/testfile.txt").Return(mfi, nil)
1748 // mfs.On("Open", "/fakeRoot/Files/testfile.txt").Return(testFile, nil)
1749 // mfs.On("Stat", "/fakeRoot/Files/.info_testfile.txt").Return(nil, errors.New("no"))
1750 // mfs.On("Stat", "/fakeRoot/Files/.rsrc_testfile.txt").Return(nil, errors.New("no"))
1754 fileTransfers: map[[4]byte]*FileTransfer{},
1756 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1758 Accounts: map[string]*Account{},
1764 NewField(FieldFileName, []byte("testfile-1k")),
1765 NewField(FieldFilePath, []byte{0x00, 0x00}),
1767 FieldFileResumeData,
1769 frd := FileResumeData{
1770 ForkCount: [2]byte{0, 2},
1771 ForkInfoList: []ForkInfoList{
1773 Fork: [4]byte{0x44, 0x41, 0x54, 0x41}, // "DATA"
1774 DataSize: [4]byte{0, 0, 0x01, 0x00}, // request offset 256
1777 Fork: [4]byte{0x4d, 0x41, 0x43, 0x52}, // "MACR"
1778 DataSize: [4]byte{0, 0, 0, 0},
1782 b, _ := frd.BinaryMarshal()
1788 wantRes: []Transaction{
1792 NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1793 NewField(FieldWaitingCount, []byte{0x00, 0x00}),
1794 NewField(FieldTransferSize, []byte{0x00, 0x00, 0x03, 0x8d}),
1795 NewField(FieldFileSize, []byte{0x00, 0x00, 0x03, 0x00}),
1801 for _, tt := range tests {
1802 t.Run(tt.name, func(t *testing.T) {
1803 gotRes := HandleDownloadFile(tt.args.cc, &tt.args.t)
1804 tranAssertEqual(t, tt.wantRes, gotRes)
1809 func TestHandleUpdateUser(t *testing.T) {
1817 wantRes []Transaction
1820 name: "when action is create user without required permission",
1823 logger: NewTestLogger(),
1825 Logger: NewTestLogger(),
1828 Access: func() accessBitmap {
1829 var bits accessBitmap
1837 NewField(FieldData, []byte{
1838 0x00, 0x04, // field count
1840 0x00, 0x69, // FieldUserLogin = 105
1844 0x00, 0x6a, // FieldUserPassword = 106
1848 0x00, 0x66, // FieldUserName = 102
1852 0x00, 0x6e, // FieldUserAccess = 110
1854 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
1858 wantRes: []Transaction{
1861 ErrorCode: [4]byte{0, 0, 0, 1},
1863 NewField(FieldError, []byte("You are not allowed to create new accounts.")),
1869 name: "when action is modify user without required permission",
1872 logger: NewTestLogger(),
1874 Logger: NewTestLogger(),
1875 Accounts: map[string]*Account{
1880 Access: func() accessBitmap {
1881 var bits accessBitmap
1889 NewField(FieldData, []byte{
1890 0x00, 0x04, // field count
1892 0x00, 0x69, // FieldUserLogin = 105
1896 0x00, 0x6a, // FieldUserPassword = 106
1900 0x00, 0x66, // FieldUserName = 102
1904 0x00, 0x6e, // FieldUserAccess = 110
1906 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
1910 wantRes: []Transaction{
1913 ErrorCode: [4]byte{0, 0, 0, 1},
1915 NewField(FieldError, []byte("You are not allowed to modify accounts.")),
1921 name: "when action is delete user without required permission",
1924 logger: NewTestLogger(),
1926 Accounts: map[string]*Account{
1931 Access: func() accessBitmap {
1932 var bits accessBitmap
1940 NewField(FieldData, []byte{
1948 wantRes: []Transaction{
1951 ErrorCode: [4]byte{0, 0, 0, 1},
1953 NewField(FieldError, []byte("You are not allowed to delete accounts.")),
1959 for _, tt := range tests {
1960 t.Run(tt.name, func(t *testing.T) {
1961 gotRes := HandleUpdateUser(tt.args.cc, &tt.args.t)
1962 tranAssertEqual(t, tt.wantRes, gotRes)
1967 func TestHandleDelNewsArt(t *testing.T) {
1975 wantRes []Transaction
1978 name: "without required permission",
1982 Access: func() accessBitmap {
1983 var bits accessBitmap
1993 wantRes: []Transaction{
1996 ErrorCode: [4]byte{0, 0, 0, 1},
1998 NewField(FieldError, []byte("You are not allowed to delete news articles.")),
2004 for _, tt := range tests {
2005 t.Run(tt.name, func(t *testing.T) {
2006 gotRes := HandleDelNewsArt(tt.args.cc, &tt.args.t)
2007 tranAssertEqual(t, tt.wantRes, gotRes)
2012 func TestHandleDisconnectUser(t *testing.T) {
2020 wantRes []Transaction
2023 name: "without required permission",
2027 Access: func() accessBitmap {
2028 var bits accessBitmap
2038 wantRes: []Transaction{
2041 ErrorCode: [4]byte{0, 0, 0, 1},
2043 NewField(FieldError, []byte("You are not allowed to disconnect users.")),
2049 name: "when target user has 'cannot be disconnected' priv",
2053 Clients: map[[2]byte]*ClientConn{
2057 Access: func() accessBitmap {
2058 var bits accessBitmap
2059 bits.Set(accessCannotBeDiscon)
2067 Access: func() accessBitmap {
2068 var bits accessBitmap
2069 bits.Set(accessDisconUser)
2077 NewField(FieldUserID, []byte{0, 1}),
2080 wantRes: []Transaction{
2083 ErrorCode: [4]byte{0, 0, 0, 1},
2085 NewField(FieldError, []byte("unnamed is not allowed to be disconnected.")),
2091 for _, tt := range tests {
2092 t.Run(tt.name, func(t *testing.T) {
2093 gotRes := HandleDisconnectUser(tt.args.cc, &tt.args.t)
2094 tranAssertEqual(t, tt.wantRes, gotRes)
2099 func TestHandleSendInstantMsg(t *testing.T) {
2107 wantRes []Transaction
2110 name: "without required permission",
2114 Access: func() accessBitmap {
2115 var bits accessBitmap
2125 wantRes: []Transaction{
2128 ErrorCode: [4]byte{0, 0, 0, 1},
2130 NewField(FieldError, []byte("You are not allowed to send private messages.")),
2136 name: "when client 1 sends a message to client 2",
2140 Access: func() accessBitmap {
2141 var bits accessBitmap
2142 bits.Set(accessSendPrivMsg)
2147 UserName: []byte("User1"),
2149 Clients: map[[2]byte]*ClientConn{
2151 AutoReply: []byte(nil),
2152 Flags: [2]byte{0, 0},
2160 NewField(FieldData, []byte("hai")),
2161 NewField(FieldUserID, []byte{0, 2}),
2164 wantRes: []Transaction{
2168 NewField(FieldData, []byte("hai")),
2169 NewField(FieldUserName, []byte("User1")),
2170 NewField(FieldUserID, []byte{0, 1}),
2171 NewField(FieldOptions, []byte{0, 1}),
2174 clientID: [2]byte{0, 1},
2176 Fields: []Field(nil),
2181 name: "when client 2 has autoreply enabled",
2185 Access: func() accessBitmap {
2186 var bits accessBitmap
2187 bits.Set(accessSendPrivMsg)
2192 UserName: []byte("User1"),
2194 Clients: map[[2]byte]*ClientConn{
2196 Flags: [2]byte{0, 0},
2198 UserName: []byte("User2"),
2199 AutoReply: []byte("autohai"),
2207 NewField(FieldData, []byte("hai")),
2208 NewField(FieldUserID, []byte{0, 2}),
2211 wantRes: []Transaction{
2215 NewField(FieldData, []byte("hai")),
2216 NewField(FieldUserName, []byte("User1")),
2217 NewField(FieldUserID, []byte{0, 1}),
2218 NewField(FieldOptions, []byte{0, 1}),
2223 NewField(FieldData, []byte("autohai")),
2224 NewField(FieldUserName, []byte("User2")),
2225 NewField(FieldUserID, []byte{0, 2}),
2226 NewField(FieldOptions, []byte{0, 1}),
2229 clientID: [2]byte{0, 1},
2231 Fields: []Field(nil),
2236 name: "when client 2 has refuse private messages enabled",
2240 Access: func() accessBitmap {
2241 var bits accessBitmap
2242 bits.Set(accessSendPrivMsg)
2247 UserName: []byte("User1"),
2249 Clients: map[[2]byte]*ClientConn{
2251 Flags: [2]byte{255, 255},
2253 UserName: []byte("User2"),
2261 NewField(FieldData, []byte("hai")),
2262 NewField(FieldUserID, []byte{0, 2}),
2265 wantRes: []Transaction{
2269 NewField(FieldData, []byte("User2 does not accept private messages.")),
2270 NewField(FieldUserName, []byte("User2")),
2271 NewField(FieldUserID, []byte{0, 2}),
2272 NewField(FieldOptions, []byte{0, 2}),
2275 clientID: [2]byte{0, 1},
2277 Fields: []Field(nil),
2282 for _, tt := range tests {
2283 t.Run(tt.name, func(t *testing.T) {
2284 gotRes := HandleSendInstantMsg(tt.args.cc, &tt.args.t)
2285 tranAssertEqual(t, tt.wantRes, gotRes)
2290 func TestHandleDeleteFile(t *testing.T) {
2298 wantRes []Transaction
2301 name: "when user does not have required permission to delete a folder",
2305 Access: func() accessBitmap {
2306 var bits accessBitmap
2312 FileRoot: func() string {
2313 return "/fakeRoot/Files"
2316 FS: func() *MockFileStore {
2317 mfi := &MockFileInfo{}
2318 mfi.On("Mode").Return(fs.FileMode(0))
2319 mfi.On("Size").Return(int64(100))
2320 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2321 mfi.On("IsDir").Return(false)
2322 mfi.On("Name").Return("testfile")
2324 mfs := &MockFileStore{}
2325 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2326 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2327 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2331 Accounts: map[string]*Account{},
2335 TranDeleteFile, [2]byte{0, 1},
2336 NewField(FieldFileName, []byte("testfile")),
2337 NewField(FieldFilePath, []byte{
2345 wantRes: []Transaction{
2348 ErrorCode: [4]byte{0, 0, 0, 1},
2350 NewField(FieldError, []byte("You are not allowed to delete files.")),
2356 name: "deletes all associated metadata files",
2360 Access: func() accessBitmap {
2361 var bits accessBitmap
2362 bits.Set(accessDeleteFile)
2368 FileRoot: func() string {
2369 return "/fakeRoot/Files"
2372 FS: func() *MockFileStore {
2373 mfi := &MockFileInfo{}
2374 mfi.On("Mode").Return(fs.FileMode(0))
2375 mfi.On("Size").Return(int64(100))
2376 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2377 mfi.On("IsDir").Return(false)
2378 mfi.On("Name").Return("testfile")
2380 mfs := &MockFileStore{}
2381 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2382 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2383 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2385 mfs.On("RemoveAll", "/fakeRoot/Files/aaa/testfile").Return(nil)
2386 mfs.On("Remove", "/fakeRoot/Files/aaa/testfile.incomplete").Return(nil)
2387 mfs.On("Remove", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil)
2388 mfs.On("Remove", "/fakeRoot/Files/aaa/.info_testfile").Return(nil)
2392 Accounts: map[string]*Account{},
2396 TranDeleteFile, [2]byte{0, 1},
2397 NewField(FieldFileName, []byte("testfile")),
2398 NewField(FieldFilePath, []byte{
2406 wantRes: []Transaction{
2409 Fields: []Field(nil),
2414 for _, tt := range tests {
2415 t.Run(tt.name, func(t *testing.T) {
2416 gotRes := HandleDeleteFile(tt.args.cc, &tt.args.t)
2417 tranAssertEqual(t, tt.wantRes, gotRes)
2419 tt.args.cc.Server.FS.(*MockFileStore).AssertExpectations(t)
2424 func TestHandleGetFileNameList(t *testing.T) {
2432 wantRes []Transaction
2435 name: "when FieldFilePath is a drop box, but user does not have accessViewDropBoxes ",
2439 Access: func() accessBitmap {
2440 var bits accessBitmap
2447 FileRoot: func() string {
2448 path, _ := os.Getwd()
2449 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2455 TranGetFileNameList, [2]byte{0, 1},
2456 NewField(FieldFilePath, []byte{
2460 0x64, 0x72, 0x6f, 0x70, 0x20, 0x62, 0x6f, 0x78, // "drop box"
2464 wantRes: []Transaction{
2467 ErrorCode: [4]byte{0, 0, 0, 1},
2469 NewField(FieldError, []byte("You are not allowed to view drop boxes.")),
2475 name: "with file root",
2480 FileRoot: func() string {
2481 path, _ := os.Getwd()
2482 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2488 TranGetFileNameList, [2]byte{0, 1},
2489 NewField(FieldFilePath, []byte{
2495 wantRes: []Transaction{
2500 FieldFileNameWithInfo,
2502 fnwi := FileNameWithInfo{
2503 fileNameWithInfoHeader: fileNameWithInfoHeader{
2504 Type: [4]byte{0x54, 0x45, 0x58, 0x54},
2505 Creator: [4]byte{0x54, 0x54, 0x58, 0x54},
2506 FileSize: [4]byte{0, 0, 0x04, 0},
2508 NameScript: [2]byte{},
2509 NameSize: [2]byte{0, 0x0b},
2511 Name: []byte("testfile-1k"),
2513 b, _ := io.ReadAll(&fnwi)
2522 for _, tt := range tests {
2523 t.Run(tt.name, func(t *testing.T) {
2524 gotRes := HandleGetFileNameList(tt.args.cc, &tt.args.t)
2525 tranAssertEqual(t, tt.wantRes, gotRes)
2530 func TestHandleGetClientInfoText(t *testing.T) {
2538 wantRes []Transaction
2541 name: "when user does not have required permission",
2545 Access: func() accessBitmap {
2546 var bits accessBitmap
2551 Accounts: map[string]*Account{},
2555 TranGetClientInfoText, [2]byte{0, 1},
2556 NewField(FieldUserID, []byte{0, 1}),
2559 wantRes: []Transaction{
2562 ErrorCode: [4]byte{0, 0, 0, 1},
2564 NewField(FieldError, []byte("You are not allowed to get client info.")),
2570 name: "with a valid user",
2573 UserName: []byte("Testy McTest"),
2574 RemoteAddr: "1.2.3.4:12345",
2576 Access: func() accessBitmap {
2577 var bits accessBitmap
2578 bits.Set(accessGetClientInfo)
2585 Accounts: map[string]*Account{},
2586 Clients: map[[2]byte]*ClientConn{
2588 UserName: []byte("Testy McTest"),
2589 RemoteAddr: "1.2.3.4:12345",
2591 Access: func() accessBitmap {
2592 var bits accessBitmap
2593 bits.Set(accessGetClientInfo)
2602 transfers: map[int]map[[4]byte]*FileTransfer{
2610 TranGetClientInfoText, [2]byte{0, 1},
2611 NewField(FieldUserID, []byte{0, 1}),
2614 wantRes: []Transaction{
2618 NewField(FieldData, []byte(
2619 strings.ReplaceAll(`Nickname: Testy McTest
2622 Address: 1.2.3.4:12345
2624 -------- File Downloads ---------
2628 ------- Folder Downloads --------
2632 --------- File Uploads ----------
2636 -------- Folder Uploads ---------
2640 ------- Waiting Downloads -------
2646 NewField(FieldUserName, []byte("Testy McTest")),
2652 for _, tt := range tests {
2653 t.Run(tt.name, func(t *testing.T) {
2654 gotRes := HandleGetClientInfoText(tt.args.cc, &tt.args.t)
2655 tranAssertEqual(t, tt.wantRes, gotRes)
2660 func TestHandleTranAgreed(t *testing.T) {
2668 wantRes []Transaction
2671 name: "normal request flow",
2675 Access: func() accessBitmap {
2676 var bits accessBitmap
2677 bits.Set(accessDisconUser)
2678 bits.Set(accessAnyName)
2682 Flags: [2]byte{0, 1},
2683 Version: []byte{0, 1},
2685 logger: NewTestLogger(),
2688 BannerFile: "banner.jpg",
2693 TranAgreed, [2]byte{},
2694 NewField(FieldUserName, []byte("username")),
2695 NewField(FieldUserIconID, []byte{0, 1}),
2696 NewField(FieldOptions, []byte{0, 0}),
2699 wantRes: []Transaction{
2701 clientID: [2]byte{0, 1},
2702 Type: [2]byte{0, 0x7a},
2704 NewField(FieldBannerType, []byte("JPEG")),
2708 clientID: [2]byte{0, 1},
2715 for _, tt := range tests {
2716 t.Run(tt.name, func(t *testing.T) {
2717 gotRes := HandleTranAgreed(tt.args.cc, &tt.args.t)
2718 tranAssertEqual(t, tt.wantRes, gotRes)
2723 func TestHandleSetClientUserInfo(t *testing.T) {
2731 wantRes []Transaction
2734 name: "when client does not have accessAnyName",
2738 Access: func() accessBitmap {
2739 var bits accessBitmap
2744 UserName: []byte("Guest"),
2745 Flags: [2]byte{0, 1},
2747 Clients: map[[2]byte]*ClientConn{
2755 TranSetClientUserInfo, [2]byte{},
2756 NewField(FieldUserIconID, []byte{0, 1}),
2757 NewField(FieldUserName, []byte("NOPE")),
2760 wantRes: []Transaction{
2762 clientID: [2]byte{0, 1},
2763 Type: [2]byte{0x01, 0x2d},
2765 NewField(FieldUserID, []byte{0, 1}),
2766 NewField(FieldUserIconID, []byte{0, 1}),
2767 NewField(FieldUserFlags, []byte{0, 1}),
2768 NewField(FieldUserName, []byte("Guest"))},
2773 for _, tt := range tests {
2774 t.Run(tt.name, func(t *testing.T) {
2775 gotRes := HandleSetClientUserInfo(tt.args.cc, &tt.args.t)
2776 tranAssertEqual(t, tt.wantRes, gotRes)
2781 func TestHandleDelNewsItem(t *testing.T) {
2789 wantRes []Transaction
2792 name: "when user does not have permission to delete a news category",
2796 Access: accessBitmap{},
2800 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
2802 Type: [2]byte{0, 3},
2809 TranDelNewsItem, [2]byte{},
2810 NewField(FieldNewsPath,
2815 0x74, 0x65, 0x73, 0x74,
2820 wantRes: []Transaction{
2822 clientID: [2]byte{0, 1},
2824 ErrorCode: [4]byte{0, 0, 0, 1},
2826 NewField(FieldError, []byte("You are not allowed to delete news categories.")),
2832 name: "when user does not have permission to delete a news folder",
2836 Access: accessBitmap{},
2840 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
2842 Type: [2]byte{0, 2},
2849 TranDelNewsItem, [2]byte{},
2850 NewField(FieldNewsPath,
2855 0x74, 0x65, 0x73, 0x74,
2860 wantRes: []Transaction{
2862 clientID: [2]byte{0, 1},
2864 ErrorCode: [4]byte{0, 0, 0, 1},
2866 NewField(FieldError, []byte("You are not allowed to delete news folders.")),
2872 name: "when user deletes a news folder",
2876 Access: func() accessBitmap {
2877 var bits accessBitmap
2878 bits.Set(accessNewsDeleteFldr)
2884 ConfigDir: "/fakeConfigRoot",
2885 FS: func() *MockFileStore {
2886 mfs := &MockFileStore{}
2887 mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
2890 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
2892 Type: [2]byte{0, 2},
2899 TranDelNewsItem, [2]byte{},
2900 NewField(FieldNewsPath,
2905 0x74, 0x65, 0x73, 0x74,
2910 wantRes: []Transaction{
2912 clientID: [2]byte{0, 1},
2919 for _, tt := range tests {
2920 t.Run(tt.name, func(t *testing.T) {
2921 gotRes := HandleDelNewsItem(tt.args.cc, &tt.args.t)
2923 tranAssertEqual(t, tt.wantRes, gotRes)
2928 func TestHandleTranOldPostNews(t *testing.T) {
2936 wantRes []Transaction
2939 name: "when user does not have required permission",
2943 Access: func() accessBitmap {
2944 var bits accessBitmap
2950 TranOldPostNews, [2]byte{0, 1},
2951 NewField(FieldData, []byte("hai")),
2954 wantRes: []Transaction{
2957 ErrorCode: [4]byte{0, 0, 0, 1},
2959 NewField(FieldError, []byte("You are not allowed to post news.")),
2965 name: "when user posts news update",
2969 Access: func() accessBitmap {
2970 var bits accessBitmap
2971 bits.Set(accessNewsPostArt)
2976 FS: func() *MockFileStore {
2977 mfs := &MockFileStore{}
2978 mfs.On("WriteFile", "/fakeConfigRoot/MessageBoard.txt", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
2981 ConfigDir: "/fakeConfigRoot",
2986 TranOldPostNews, [2]byte{0, 1},
2987 NewField(FieldData, []byte("hai")),
2990 wantRes: []Transaction{
2997 for _, tt := range tests {
2998 t.Run(tt.name, func(t *testing.T) {
2999 gotRes := HandleTranOldPostNews(tt.args.cc, &tt.args.t)
3001 tranAssertEqual(t, tt.wantRes, gotRes)
3006 func TestHandleInviteNewChat(t *testing.T) {
3014 wantRes []Transaction
3017 name: "when user does not have required permission",
3021 Access: func() accessBitmap {
3022 var bits accessBitmap
3027 t: NewTransaction(TranInviteNewChat, [2]byte{0, 1}),
3029 wantRes: []Transaction{
3032 ErrorCode: [4]byte{0, 0, 0, 1},
3034 NewField(FieldError, []byte("You are not allowed to request private chat.")),
3040 name: "when userA invites userB to new private chat",
3045 Access: func() accessBitmap {
3046 var bits accessBitmap
3047 bits.Set(accessOpenChat)
3051 UserName: []byte("UserA"),
3053 Flags: [2]byte{0, 0},
3055 Clients: map[[2]byte]*ClientConn{
3058 UserName: []byte("UserB"),
3061 PrivateChats: make(map[[4]byte]*PrivateChat),
3065 TranInviteNewChat, [2]byte{0, 1},
3066 NewField(FieldUserID, []byte{0, 2}),
3069 wantRes: []Transaction{
3071 clientID: [2]byte{0, 2},
3072 Type: [2]byte{0, 0x71},
3074 NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3075 NewField(FieldUserName, []byte("UserA")),
3076 NewField(FieldUserID, []byte{0, 1}),
3081 clientID: [2]byte{0, 1},
3084 NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3085 NewField(FieldUserName, []byte("UserA")),
3086 NewField(FieldUserID, []byte{0, 1}),
3087 NewField(FieldUserIconID, []byte{0, 1}),
3088 NewField(FieldUserFlags, []byte{0, 0}),
3094 name: "when userA invites userB to new private chat, but UserB has refuse private chat enabled",
3099 Access: func() accessBitmap {
3100 var bits accessBitmap
3101 bits.Set(accessOpenChat)
3105 UserName: []byte("UserA"),
3107 Flags: [2]byte{0, 0},
3109 Clients: map[[2]byte]*ClientConn{
3112 UserName: []byte("UserB"),
3113 Flags: [2]byte{255, 255},
3116 PrivateChats: make(map[[4]byte]*PrivateChat),
3120 TranInviteNewChat, [2]byte{0, 1},
3121 NewField(FieldUserID, []byte{0, 2}),
3124 wantRes: []Transaction{
3126 clientID: [2]byte{0, 1},
3127 Type: [2]byte{0, 0x68},
3129 NewField(FieldData, []byte("UserB does not accept private chats.")),
3130 NewField(FieldUserName, []byte("UserB")),
3131 NewField(FieldUserID, []byte{0, 2}),
3132 NewField(FieldOptions, []byte{0, 2}),
3136 clientID: [2]byte{0, 1},
3139 NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3140 NewField(FieldUserName, []byte("UserA")),
3141 NewField(FieldUserID, []byte{0, 1}),
3142 NewField(FieldUserIconID, []byte{0, 1}),
3143 NewField(FieldUserFlags, []byte{0, 0}),
3149 for _, tt := range tests {
3150 t.Run(tt.name, func(t *testing.T) {
3151 gotRes := HandleInviteNewChat(tt.args.cc, &tt.args.t)
3153 tranAssertEqual(t, tt.wantRes, gotRes)
3158 func TestHandleGetNewsArtData(t *testing.T) {
3166 wantRes []Transaction
3169 name: "when user does not have required permission",
3173 Access: func() accessBitmap {
3174 var bits accessBitmap
3179 Accounts: map[string]*Account{},
3183 TranGetNewsArtData, [2]byte{0, 1},
3186 wantRes: []Transaction{
3189 ErrorCode: [4]byte{0, 0, 0, 1},
3191 NewField(FieldError, []byte("You are not allowed to read news.")),
3197 for _, tt := range tests {
3198 t.Run(tt.name, func(t *testing.T) {
3199 gotRes := HandleGetNewsArtData(tt.args.cc, &tt.args.t)
3200 tranAssertEqual(t, tt.wantRes, gotRes)
3205 func TestHandleGetNewsArtNameList(t *testing.T) {
3213 wantRes []Transaction
3216 name: "when user does not have required permission",
3220 Access: func() accessBitmap {
3221 var bits accessBitmap
3226 Accounts: map[string]*Account{},
3230 TranGetNewsArtNameList, [2]byte{0, 1},
3233 wantRes: []Transaction{
3237 Type: [2]byte{0, 0},
3238 ErrorCode: [4]byte{0, 0, 0, 1},
3240 NewField(FieldError, []byte("You are not allowed to read news.")),
3246 name: "when user has required access",
3250 Access: func() accessBitmap {
3251 var bits accessBitmap
3252 bits.Set(accessNewsReadArt)
3257 ThreadedNews: &ThreadedNews{
3258 Categories: map[string]NewsCategoryListData15{
3259 "Example Category": {
3260 Type: [2]byte{0, 2},
3262 Articles: map[uint32]*NewsArtData{
3265 Poster: "testPoster",
3272 DeleteSN: [4]byte{},
3277 //Accounts: map[string]*Account{
3282 // Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
3288 TranGetNewsArtNameList,
3290 // 00000000 00 01 00 00 10 45 78 61 6d 70 6c 65 20 43 61 74 |.....Example Cat|
3291 // 00000010 65 67 6f 72 79 |egory|
3292 NewField(FieldNewsPath, []byte{
3293 0x00, 0x01, 0x00, 0x00, 0x10, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79,
3297 wantRes: []Transaction{
3301 NewField(FieldNewsArtListData, []byte{
3302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
3303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
3304 0x09, 0x74, 0x65, 0x73, 0x74, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x50,
3305 0x6f, 0x73, 0x74, 0x65, 0x72, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e,
3314 for _, tt := range tests {
3315 t.Run(tt.name, func(t *testing.T) {
3316 gotRes := HandleGetNewsArtNameList(tt.args.cc, &tt.args.t)
3318 tranAssertEqual(t, tt.wantRes, gotRes)
3323 func TestHandleNewNewsFldr(t *testing.T) {
3331 wantRes []Transaction
3334 name: "when user does not have required permission",
3338 Access: func() accessBitmap {
3339 var bits accessBitmap
3344 Accounts: map[string]*Account{},
3348 TranGetNewsArtNameList, [2]byte{0, 1},
3351 wantRes: []Transaction{
3355 Type: [2]byte{0, 0},
3356 ErrorCode: [4]byte{0, 0, 0, 1},
3358 NewField(FieldError, []byte("You are not allowed to create news folders.")),
3364 name: "with a valid request",
3368 Access: func() accessBitmap {
3369 var bits accessBitmap
3370 bits.Set(accessNewsCreateFldr)
3374 logger: NewTestLogger(),
3377 ConfigDir: "/fakeConfigRoot",
3378 FS: func() *MockFileStore {
3379 mfs := &MockFileStore{}
3380 mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(nil)
3383 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3385 Type: [2]byte{0, 2},
3387 SubCats: make(map[string]NewsCategoryListData15),
3393 TranGetNewsArtNameList, [2]byte{0, 1},
3394 NewField(FieldFileName, []byte("testFolder")),
3395 NewField(FieldNewsPath,
3400 0x74, 0x65, 0x73, 0x74,
3405 wantRes: []Transaction{
3407 clientID: [2]byte{0, 1},
3414 // Name: "when there is an error writing the threaded news file",
3417 // Account: &Account{
3418 // Access: func() accessBitmap {
3419 // var bits accessBitmap
3420 // bits.Set(accessNewsCreateFldr)
3424 // logger: NewTestLogger(),
3425 // ID: [2]byte{0, 1},
3427 // ConfigDir: "/fakeConfigRoot",
3428 // FS: func() *MockFileStore {
3429 // mfs := &MockFileStore{}
3430 // mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(os.ErrNotExist)
3433 // ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3435 // Type: []byte{0, 2},
3439 // SubCats: make(map[string]NewsCategoryListData15),
3444 // t: NewTransaction(
3445 // TranGetNewsArtNameList, [2]byte{0, 1},
3446 // NewField(FieldFileName, []byte("testFolder")),
3447 // NewField(FieldNewsPath,
3452 // 0x74, 0x65, 0x73, 0x74,
3457 // wantRes: []Transaction{
3459 // clientID: [2]byte{0, 1},
3462 // Type: [2]byte{0, 0},
3463 // ErrorCode: [4]byte{0, 0, 0, 1},
3465 // NewField(FieldError, []byte("Error creating news folder.")),
3470 for _, tt := range tests {
3471 t.Run(tt.name, func(t *testing.T) {
3472 gotRes := HandleNewNewsFldr(tt.args.cc, &tt.args.t)
3474 tranAssertEqual(t, tt.wantRes, gotRes)
3479 func TestHandleDownloadBanner(t *testing.T) {
3487 wantRes []Transaction
3489 // TODO: Add test cases.
3491 for _, tt := range tests {
3492 t.Run(tt.name, func(t *testing.T) {
3493 gotRes := HandleDownloadBanner(tt.args.cc, &tt.args.t)
3495 assert.Equalf(t, tt.wantRes, gotRes, "HandleDownloadBanner(%v, %v)", tt.args.cc, &tt.args.t)
3500 func TestHandlePostNewsArt(t *testing.T) {
3508 wantRes []Transaction
3511 name: "without required permission",
3515 Access: func() accessBitmap {
3516 var bits accessBitmap
3526 wantRes: []Transaction{
3529 ErrorCode: [4]byte{0, 0, 0, 1},
3531 NewField(FieldError, []byte("You are not allowed to post news articles.")),
3537 name: "with required permission",
3541 FS: func() *MockFileStore {
3542 mfs := &MockFileStore{}
3543 mfs.On("WriteFile", "ThreadedNews.yaml", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
3547 threadedNewsMux: sync.Mutex{},
3548 ThreadedNews: &ThreadedNews{
3549 Categories: map[string]NewsCategoryListData15{
3553 Articles: map[uint32]*NewsArtData{},
3557 DeleteSN: [4]byte{},
3564 Access: func() accessBitmap {
3565 var bits accessBitmap
3566 bits.Set(accessNewsPostArt)
3574 NewField(FieldNewsPath, []byte{0x00, 0x01, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77}),
3575 NewField(FieldNewsArtID, []byte{0x00, 0x00, 0x00, 0x00}),
3578 wantRes: []Transaction{
3581 ErrorCode: [4]byte{0, 0, 0, 0},
3587 for _, tt := range tests {
3588 t.Run(tt.name, func(t *testing.T) {
3589 tranAssertEqual(t, tt.wantRes, HandlePostNewsArt(tt.args.cc, &tt.args.t))