]> git.r.bdr.sh - rbdr/mobius/blobdiff - hotline/transaction_handlers_test.go
Extensive refactor and clean up
[rbdr/mobius] / hotline / transaction_handlers_test.go
index b7cc0afbc609ac78dbaeea3506f0029fa57b8bce..610e11399f7516467b844f0fe053598cc5596f76 100644 (file)
@@ -9,7 +9,6 @@ import (
        "os"
        "path/filepath"
        "strings"
-       "sync"
        "testing"
        "time"
 )
@@ -30,39 +29,63 @@ func TestHandleSetChatSubject(t *testing.T) {
                                cc: &ClientConn{
                                        UserName: []byte{0x00, 0x01},
                                        Server: &Server{
-                                               PrivateChats: map[[4]byte]*PrivateChat{
-                                                       [4]byte{0, 0, 0, 1}: {
-                                                               Subject: "unset",
-                                                               ClientConn: map[[2]byte]*ClientConn{
-                                                                       [2]byte{0, 1}: {
-                                                                               Account: &Account{
-                                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
-                                                                               },
-                                                                               ID: [2]byte{0, 1},
+                                               ChatMgr: func() *MockChatManager {
+                                                       m := MockChatManager{}
+                                                       m.On("Members", ChatID{0x0, 0x0, 0x0, 0x1}).Return([]*ClientConn{
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
                                                                        },
-                                                                       [2]byte{0, 2}: {
-                                                                               Account: &Account{
-                                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
-                                                                               },
-                                                                               ID: [2]byte{0, 2},
+                                                                       ID: [2]byte{0, 1},
+                                                               },
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
                                                                        },
+                                                                       ID: [2]byte{0, 2},
                                                                },
-                                                       },
-                                               },
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                       })
+                                                       m.On("SetSubject", ChatID{0x0, 0x0, 0x0, 0x1}, "Test Subject")
+                                                       return &m
+                                               }(),
+                                               //PrivateChats: map[[4]byte]*PrivateChat{
+                                               //      [4]byte{0, 0, 0, 1}: {
+                                               //              Subject: "unset",
+                                               //              ClientConn: map[[2]byte]*ClientConn{
+                                               //                      [2]byte{0, 1}: {
+                                               //                              Account: &Account{
+                                               //                                      Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                               //                              },
+                                               //                              ID: [2]byte{0, 1},
+                                               //                      },
+                                               //                      [2]byte{0, 2}: {
+                                               //                              Account: &Account{
+                                               //                                      Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                               //                              },
+                                               //                              ID: [2]byte{0, 2},
+                                               //                      },
+                                               //              },
+                                               //      },
+                                               //},
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 1},
                                                                },
-                                                               ID: [2]byte{0, 1},
-                                                       },
-                                                       [2]byte{0, 2}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 2},
                                                                },
-                                                               ID: [2]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: Transaction{
@@ -115,43 +138,44 @@ func TestHandleLeaveChat(t *testing.T) {
                want []Transaction
        }{
                {
-                       name: "returns expected transactions",
+                       name: "when client 2 leaves chat",
                        args: args{
                                cc: &ClientConn{
                                        ID: [2]byte{0, 2},
                                        Server: &Server{
-                                               PrivateChats: map[[4]byte]*PrivateChat{
-                                                       [4]byte{0, 0, 0, 1}: {
-                                                               ClientConn: map[[2]byte]*ClientConn{
-                                                                       [2]byte{0, 1}: {
-                                                                               Account: &Account{
-                                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
-                                                                               },
-                                                                               ID: [2]byte{0, 1},
-                                                                       },
-                                                                       [2]byte{0, 2}: {
-                                                                               Account: &Account{
-                                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
-                                                                               },
-                                                                               ID: [2]byte{0, 2},
+                                               ChatMgr: func() *MockChatManager {
+                                                       m := MockChatManager{}
+                                                       m.On("Members", ChatID{0x0, 0x0, 0x0, 0x1}).Return([]*ClientConn{
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
                                                                        },
+                                                                       ID: [2]byte{0, 1},
                                                                },
-                                                       },
-                                               },
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                       })
+                                                       m.On("Leave", ChatID{0x0, 0x0, 0x0, 0x1}, [2]uint8{0x0, 0x2})
+                                                       m.On("GetSubject").Return("unset")
+                                                       return &m
+                                               }(),
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("Get").Return([]*ClientConn{
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 1},
                                                                },
-                                                               ID: [2]byte{0, 1},
-                                                       },
-                                                       [2]byte{0, 2}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 2},
                                                                },
-                                                               ID: [2]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(TranDeleteUser, [2]byte{}, NewField(FieldChatID, []byte{0, 0, 0, 1})),
@@ -194,20 +218,25 @@ func TestHandleGetUserNameList(t *testing.T) {
                                cc: &ClientConn{
                                        ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
-                                                               ID:       [2]byte{0, 1},
-                                                               Icon:     []byte{0, 2},
-                                                               Flags:    [2]byte{0, 3},
-                                                               UserName: []byte{0, 4},
-                                                       },
-                                                       [2]byte{0, 2}: {
-                                                               ID:       [2]byte{0, 2},
-                                                               Icon:     []byte{0, 2},
-                                                               Flags:    [2]byte{0, 3},
-                                                               UserName: []byte{0, 4},
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               {
+                                                                       ID:       [2]byte{0, 1},
+                                                                       Icon:     []byte{0, 2},
+                                                                       Flags:    [2]byte{0, 3},
+                                                                       UserName: []byte{0, 4},
+                                                               },
+                                                               {
+                                                                       ID:       [2]byte{0, 2},
+                                                                       Icon:     []byte{0, 2},
+                                                                       Flags:    [2]byte{0, 3},
+                                                                       UserName: []byte{0, 4},
+                                                               },
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: Transaction{},
@@ -255,26 +284,31 @@ func TestHandleChatSend(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendChat)
+                                                       bits.Set(AccessSendChat)
                                                        return bits
                                                }(),
                                        },
                                        UserName: []byte{0x00, 0x01},
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 1},
                                                                },
-                                                               ID: [2]byte{0, 1},
-                                                       },
-                                                       [2]byte{0, 2}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 2},
                                                                },
-                                                               ID: [2]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: Transaction{
@@ -305,32 +339,37 @@ func TestHandleChatSend(t *testing.T) {
                        },
                },
                {
-                       name: "treats Chat ID 00 00 00 00 as a public chat message",
+                       name: "treats Chat Type 00 00 00 00 as a public chat message",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendChat)
+                                                       bits.Set(AccessSendChat)
                                                        return bits
                                                }(),
                                        },
                                        UserName: []byte{0x00, 0x01},
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 1},
                                                                },
-                                                               ID: [2]byte{0, 1},
-                                                       },
-                                                       [2]byte{0, 2}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 2},
                                                                },
-                                                               ID: [2]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: Transaction{
@@ -368,7 +407,7 @@ func TestHandleChatSend(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -393,26 +432,31 @@ func TestHandleChatSend(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendChat)
+                                                       bits.Set(AccessSendChat)
                                                        return bits
                                                }(),
                                        },
                                        UserName: []byte("Testy McTest"),
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 1},
                                                                },
-                                                               ID: [2]byte{0, 1},
-                                                       },
-                                                       [2]byte{0, 2}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 2},
                                                                },
-                                                               ID: [2]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: Transaction{
@@ -450,26 +494,31 @@ func TestHandleChatSend(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendChat)
+                                                       bits.Set(AccessSendChat)
                                                        return bits
                                                }(),
                                        },
                                        UserName: []byte("Testy McTest"),
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 1},
                                                                },
-                                                               ID: [2]byte{0, 1},
-                                                       },
-                                                       [2]byte{0, 2}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 2},
                                                                },
-                                                               ID: [2]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: Transaction{
@@ -497,35 +546,39 @@ func TestHandleChatSend(t *testing.T) {
                        },
                },
                {
-                       name: "only sends chat msg to clients with accessReadChat permission",
+                       name: "only sends chat msg to clients with AccessReadChat permission",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendChat)
+                                                       bits.Set(AccessSendChat)
                                                        return bits
                                                }(),
                                        },
                                        UserName: []byte{0x00, 0x01},
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
-                                                               Account: &Account{
-                                                                       Access: func() accessBitmap {
-                                                                               var bits accessBitmap
-                                                                               bits.Set(accessReadChat)
-                                                                               return bits
-                                                                       }()},
-                                                               ID: [2]byte{0, 1},
-                                                       },
-                                                       [2]byte{0, 2}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: func() accessBitmap {
+                                                                                       var bits accessBitmap
+                                                                                       bits.Set(AccessReadChat)
+                                                                                       return bits
+                                                                               }(),
+                                                                       },
+                                                                       ID: [2]byte{0, 1},
+                                                               },
+                                                               {
+                                                                       Account: &Account{},
+                                                                       ID:      [2]byte{0, 2},
                                                                },
-                                                               ID: [2]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: Transaction{
@@ -551,44 +604,50 @@ func TestHandleChatSend(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendChat)
+                                                       bits.Set(AccessSendChat)
                                                        return bits
                                                }(),
                                        },
                                        UserName: []byte{0x00, 0x01},
                                        Server: &Server{
-                                               PrivateChats: map[[4]byte]*PrivateChat{
-                                                       [4]byte{0, 0, 0, 1}: {
-                                                               ClientConn: map[[2]byte]*ClientConn{
-                                                                       [2]byte{0, 1}: {
-                                                                               ID: [2]byte{0, 1},
-                                                                       },
-                                                                       [2]byte{0, 2}: {
-                                                                               ID: [2]byte{0, 2},
-                                                                       },
+                                               ChatMgr: func() *MockChatManager {
+                                                       m := MockChatManager{}
+                                                       m.On("Members", ChatID{0x0, 0x0, 0x0, 0x1}).Return([]*ClientConn{
+                                                               {
+                                                                       ID: [2]byte{0, 1},
                                                                },
-                                                       },
-                                               },
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                               {
+                                                                       ID: [2]byte{0, 2},
                                                                },
-                                                               ID: [2]byte{0, 1},
-                                                       },
-                                                       [2]byte{0, 2}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
+                                                       })
+                                                       m.On("GetSubject").Return("unset")
+                                                       return &m
+                                               }(),
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                                       },
+                                                                       ID: [2]byte{0, 1},
                                                                },
-                                                               ID: [2]byte{0, 2},
-                                                       },
-                                                       [2]byte{0, 3}: {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
+                                                                       },
+                                                                       ID: [2]byte{0, 2},
+                                                               },
+                                                               {
+                                                                       Account: &Account{
+                                                                               Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
+                                                                       },
+                                                                       ID: [2]byte{0, 3},
                                                                },
-                                                               ID: [2]byte{0, 3},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: Transaction{
@@ -643,7 +702,7 @@ func TestHandleGetFileInfo(t *testing.T) {
                                        ID: [2]byte{0x00, 0x01},
                                        Server: &Server{
                                                FS: &OSFileStore{},
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: func() string {
                                                                path, _ := os.Getwd()
                                                                return filepath.Join(path, "/test/config/Files")
@@ -734,13 +793,13 @@ func TestHandleNewFolder(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessCreateFolder)
+                                                       bits.Set(AccessCreateFolder)
                                                        return bits
                                                }(),
                                        },
                                        ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: "/Files/",
                                                },
                                                FS: func() *MockFileStore {
@@ -776,13 +835,13 @@ func TestHandleNewFolder(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessCreateFolder)
+                                                       bits.Set(AccessCreateFolder)
                                                        return bits
                                                }(),
                                        },
                                        ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: "/Files",
                                                },
                                                FS: func() *MockFileStore {
@@ -812,13 +871,13 @@ func TestHandleNewFolder(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessCreateFolder)
+                                                       bits.Set(AccessCreateFolder)
                                                        return bits
                                                }(),
                                        },
                                        ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: "/Files/",
                                                },
                                                FS: func() *MockFileStore {
@@ -846,13 +905,13 @@ func TestHandleNewFolder(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessCreateFolder)
+                                                       bits.Set(AccessCreateFolder)
                                                        return bits
                                                }(),
                                        },
                                        ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: "/Files/",
                                                },
                                                FS: func() *MockFileStore {
@@ -882,13 +941,13 @@ func TestHandleNewFolder(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessCreateFolder)
+                                                       bits.Set(AccessCreateFolder)
                                                        return bits
                                                }(),
                                        },
                                        ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: "/Files/",
                                                },
                                                FS: func() *MockFileStore {
@@ -947,19 +1006,17 @@ func TestHandleUploadFile(t *testing.T) {
                        args: args{
                                cc: &ClientConn{
                                        Server: &Server{
-                                               FS:            &OSFileStore{},
-                                               fileTransfers: map[[4]byte]*FileTransfer{},
-                                               Config: &Config{
+                                               FS:              &OSFileStore{},
+                                               FileTransferMgr: NewMemFileTransferMgr(),
+                                               Config: Config{
                                                        FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
                                                }},
-                                       transfers: map[int]map[[4]byte]*FileTransfer{
-                                               FileUpload: {},
-                                       },
+                                       ClientFileTransferMgr: NewClientFileTransferMgr(),
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessUploadFile)
-                                                       bits.Set(accessUploadAnywhere)
+                                                       bits.Set(AccessUploadFile)
+                                                       bits.Set(AccessUploadAnywhere)
                                                        return bits
                                                }(),
                                        },
@@ -1043,12 +1100,12 @@ func TestHandleMakeAlias(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessMakeAlias)
+                                                       bits.Set(AccessMakeAlias)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: func() string {
                                                                path, _ := os.Getwd()
                                                                return path + "/test/config/Files"
@@ -1089,12 +1146,12 @@ func TestHandleMakeAlias(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessMakeAlias)
+                                                       bits.Set(AccessMakeAlias)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: func() string {
                                                                path, _ := os.Getwd()
                                                                return path + "/test/config/Files"
@@ -1136,13 +1193,10 @@ func TestHandleMakeAlias(t *testing.T) {
                                cc: &ClientConn{
                                        logger: NewTestLogger(),
                                        Account: &Account{
-                                               Access: func() accessBitmap {
-                                                       var bits accessBitmap
-                                                       return bits
-                                               }(),
+                                               Access: accessBitmap{},
                                        },
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: func() string {
                                                                path, _ := os.Getwd()
                                                                return path + "/test/config/Files"
@@ -1203,19 +1257,21 @@ func TestHandleGetUser(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessOpenUser)
+                                                       bits.Set(AccessOpenUser)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{
-                                                       "guest": {
+                                               AccountManager: func() *MockAccountManager {
+                                                       m := MockAccountManager{}
+                                                       m.On("Get", "guest").Return(&Account{
                                                                Login:    "guest",
                                                                Name:     "Guest",
                                                                Password: "password",
                                                                Access:   accessBitmap{},
-                                                       },
-                                               },
+                                                       })
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -1246,7 +1302,7 @@ func TestHandleGetUser(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -1271,12 +1327,16 @@ func TestHandleGetUser(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessOpenUser)
+                                                       bits.Set(AccessOpenUser)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               AccountManager: func() *MockAccountManager {
+                                                       m := MockAccountManager{}
+                                                       m.On("Get", "nonExistentUser").Return((*Account)(nil))
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -1316,29 +1376,26 @@ func TestHandleDeleteUser(t *testing.T) {
                wantRes []Transaction
        }{
                {
-                       name: "when user dataFile",
+                       name: "when user exists",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessDeleteUser)
+                                                       bits.Set(AccessDeleteUser)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{
-                                                       "testuser": {
-                                                               Login:    "testuser",
-                                                               Name:     "Testy McTest",
-                                                               Password: "password",
-                                                               Access:   accessBitmap{},
-                                                       },
-                                               },
-                                               FS: func() *MockFileStore {
-                                                       mfs := &MockFileStore{}
-                                                       mfs.On("Remove", "Users/testuser.yaml").Return(nil)
-                                                       return mfs
+                                               AccountManager: func() *MockAccountManager {
+                                                       m := MockAccountManager{}
+                                                       m.On("Delete", "testuser").Return(nil)
+                                                       return &m
+                                               }(),
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{}) // TODO
+                                                       return &m
                                                }(),
                                        },
                                },
@@ -1361,13 +1418,10 @@ func TestHandleDeleteUser(t *testing.T) {
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
-                                               Access: func() accessBitmap {
-                                                       var bits accessBitmap
-                                                       return bits
-                                               }(),
+                                               Access: accessBitmap{},
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -1411,12 +1465,20 @@ func TestHandleGetMsgs(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessNewsReadArt)
+                                                       bits.Set(AccessNewsReadArt)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               FlatNews: []byte("TEST"),
+                                               MessageBoard: func() *mockReadWriteSeeker {
+                                                       m := mockReadWriteSeeker{}
+                                                       m.On("Seek", int64(0), 0).Return(int64(0), nil)
+                                                       m.On("Read", mock.AnythingOfType("[]uint8")).Run(func(args mock.Arguments) {
+                                                               arg := args.Get(0).([]uint8)
+                                                               copy(arg, "TEST")
+                                                       }).Return(4, io.EOF)
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -1437,13 +1499,10 @@ func TestHandleGetMsgs(t *testing.T) {
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
-                                               Access: func() accessBitmap {
-                                                       var bits accessBitmap
-                                                       return bits
-                                               }(),
+                                               Access: accessBitmap{},
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -1490,7 +1549,7 @@ func TestHandleNewUser(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -1514,22 +1573,26 @@ func TestHandleNewUser(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessCreateUser)
+                                                       bits.Set(AccessCreateUser)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               AccountManager: func() *MockAccountManager {
+                                                       m := MockAccountManager{}
+                                                       m.On("Get", "userB").Return((*Account)(nil))
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
                                        TranNewUser, [2]byte{0, 1},
-                                       NewField(FieldUserLogin, []byte("userB")),
+                                       NewField(FieldUserLogin, encodeString([]byte("userB"))),
                                        NewField(
                                                FieldUserAccess,
                                                func() []byte {
                                                        var bits accessBitmap
-                                                       bits.Set(accessDisconUser)
+                                                       bits.Set(AccessDisconUser)
                                                        return bits[:]
                                                }(),
                                        ),
@@ -1575,7 +1638,7 @@ func TestHandleListUsers(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -1599,19 +1662,23 @@ func TestHandleListUsers(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessOpenUser)
+                                                       bits.Set(AccessOpenUser)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{
-                                                       "guest": {
-                                                               Name:     "guest",
-                                                               Login:    "guest",
-                                                               Password: "zz",
-                                                               Access:   accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
-                                                       },
-                                               },
+                                               AccountManager: func() *MockAccountManager {
+                                                       m := MockAccountManager{}
+                                                       m.On("List").Return([]Account{
+                                                               {
+                                                                       Name:     "guest",
+                                                                       Login:    "guest",
+                                                                       Password: "zz",
+                                                                       Access:   accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                               },
+                                                       })
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -1680,23 +1747,20 @@ func TestHandleDownloadFile(t *testing.T) {
                        name: "with a valid file",
                        args: args{
                                cc: &ClientConn{
-                                       transfers: map[int]map[[4]byte]*FileTransfer{
-                                               FileDownload: {},
-                                       },
+                                       ClientFileTransferMgr: NewClientFileTransferMgr(),
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessDownloadFile)
+                                                       bits.Set(AccessDownloadFile)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               FS:            &OSFileStore{},
-                                               fileTransfers: map[[4]byte]*FileTransfer{},
-                                               Config: &Config{
+                                               FS:              &OSFileStore{},
+                                               FileTransferMgr: NewMemFileTransferMgr(),
+                                               Config: Config{
                                                        FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
                                                },
-                                               Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -1722,12 +1786,11 @@ func TestHandleDownloadFile(t *testing.T) {
                        name: "when client requests to resume 1k test file at offset 256",
                        args: args{
                                cc: &ClientConn{
-                                       transfers: map[int]map[[4]byte]*FileTransfer{
-                                               FileDownload: {},
-                                       }, Account: &Account{
+                                       ClientFileTransferMgr: NewClientFileTransferMgr(),
+                                       Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessDownloadFile)
+                                                       bits.Set(AccessDownloadFile)
                                                        return bits
                                                }(),
                                        },
@@ -1751,11 +1814,11 @@ func TestHandleDownloadFile(t *testing.T) {
                                                //
                                                //      return mfs
                                                // }(),
-                                               fileTransfers: map[[4]byte]*FileTransfer{},
-                                               Config: &Config{
+                                               FileTransferMgr: NewMemFileTransferMgr(),
+                                               Config: Config{
                                                        FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
                                                },
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -1822,13 +1885,15 @@ func TestHandleUpdateUser(t *testing.T) {
                                cc: &ClientConn{
                                        logger: NewTestLogger(),
                                        Server: &Server{
+                                               AccountManager: func() *MockAccountManager {
+                                                       m := MockAccountManager{}
+                                                       m.On("Get", "bbb").Return((*Account)(nil))
+                                                       return &m
+                                               }(),
                                                Logger: NewTestLogger(),
                                        },
                                        Account: &Account{
-                                               Access: func() accessBitmap {
-                                                       var bits accessBitmap
-                                                       return bits
-                                               }(),
+                                               Access: accessBitmap{},
                                        },
                                },
                                t: NewTransaction(
@@ -1872,9 +1937,11 @@ func TestHandleUpdateUser(t *testing.T) {
                                        logger: NewTestLogger(),
                                        Server: &Server{
                                                Logger: NewTestLogger(),
-                                               Accounts: map[string]*Account{
-                                                       "bbb": {},
-                                               },
+                                               AccountManager: func() *MockAccountManager {
+                                                       m := MockAccountManager{}
+                                                       m.On("Get", "bbb").Return(&Account{})
+                                                       return &m
+                                               }(),
                                        },
                                        Account: &Account{
                                                Access: func() accessBitmap {
@@ -1922,16 +1989,9 @@ func TestHandleUpdateUser(t *testing.T) {
                        args: args{
                                cc: &ClientConn{
                                        logger: NewTestLogger(),
-                                       Server: &Server{
-                                               Accounts: map[string]*Account{
-                                                       "bbb": {},
-                                               },
-                                       },
+                                       Server: &Server{},
                                        Account: &Account{
-                                               Access: func() accessBitmap {
-                                                       var bits accessBitmap
-                                                       return bits
-                                               }(),
+                                               Access: accessBitmap{},
                                        },
                                },
                                t: NewTransaction(
@@ -2050,23 +2110,26 @@ func TestHandleDisconnectUser(t *testing.T) {
                        args: args{
                                cc: &ClientConn{
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("Get", ClientID{0x0, 0x1}).Return(&ClientConn{
                                                                Account: &Account{
                                                                        Login: "unnamed",
                                                                        Access: func() accessBitmap {
                                                                                var bits accessBitmap
-                                                                               bits.Set(accessCannotBeDiscon)
+                                                                               bits.Set(AccessCannotBeDiscon)
                                                                                return bits
                                                                        }(),
                                                                },
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessDisconUser)
+                                                       bits.Set(AccessDisconUser)
                                                        return bits
                                                }(),
                                        },
@@ -2139,19 +2202,22 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendPrivMsg)
+                                                       bits.Set(AccessSendPrivMsg)
                                                        return bits
                                                }(),
                                        },
                                        ID:       [2]byte{0, 1},
                                        UserName: []byte("User1"),
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 2}: {
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("Get", ClientID{0x0, 0x2}).Return(&ClientConn{
                                                                AutoReply: []byte(nil),
                                                                Flags:     [2]byte{0, 0},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -2184,21 +2250,23 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendPrivMsg)
+                                                       bits.Set(AccessSendPrivMsg)
                                                        return bits
                                                }(),
                                        },
                                        ID:       [2]byte{0, 1},
                                        UserName: []byte("User1"),
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 2}: {
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("Get", ClientID{0x0, 0x2}).Return(&ClientConn{
                                                                Flags:     [2]byte{0, 0},
                                                                ID:        [2]byte{0, 2},
                                                                UserName:  []byte("User2"),
                                                                AutoReply: []byte("autohai"),
-                                                       },
-                                               },
+                                                       })
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -2239,20 +2307,23 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendPrivMsg)
+                                                       bits.Set(AccessSendPrivMsg)
                                                        return bits
                                                }(),
                                        },
                                        ID:       [2]byte{0, 1},
                                        UserName: []byte("User1"),
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 2}: {
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("Get", ClientID{0x0, 0x2}).Return(&ClientConn{
                                                                Flags:    [2]byte{255, 255},
                                                                ID:       [2]byte{0, 2},
                                                                UserName: []byte("User2"),
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -2308,7 +2379,7 @@ func TestHandleDeleteFile(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: func() string {
                                                                return "/fakeRoot/Files"
                                                        }(),
@@ -2328,7 +2399,7 @@ func TestHandleDeleteFile(t *testing.T) {
 
                                                        return mfs
                                                }(),
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -2359,12 +2430,12 @@ func TestHandleDeleteFile(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessDeleteFile)
+                                                       bits.Set(AccessDeleteFile)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: func() string {
                                                                return "/fakeRoot/Files"
                                                        }(),
@@ -2389,7 +2460,7 @@ func TestHandleDeleteFile(t *testing.T) {
 
                                                        return mfs
                                                }(),
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -2432,7 +2503,7 @@ func TestHandleGetFileNameList(t *testing.T) {
                wantRes []Transaction
        }{
                {
-                       name: "when FieldFilePath is a drop box, but user does not have accessViewDropBoxes ",
+                       name: "when FieldFilePath is a drop box, but user does not have AccessViewDropBoxes ",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
@@ -2443,7 +2514,7 @@ func TestHandleGetFileNameList(t *testing.T) {
                                        },
                                        Server: &Server{
 
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: func() string {
                                                                path, _ := os.Getwd()
                                                                return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
@@ -2476,7 +2547,7 @@ func TestHandleGetFileNameList(t *testing.T) {
                        args: args{
                                cc: &ClientConn{
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: func() string {
                                                                path, _ := os.Getwd()
                                                                return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
@@ -2548,7 +2619,7 @@ func TestHandleGetClientInfoText(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -2575,36 +2646,33 @@ func TestHandleGetClientInfoText(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessGetClientInfo)
+                                                       bits.Set(AccessGetClientInfo)
                                                        return bits
                                                }(),
                                                Name:  "test",
                                                Login: "test",
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("Get", ClientID{0x0, 0x1}).Return(&ClientConn{
                                                                UserName:   []byte("Testy McTest"),
                                                                RemoteAddr: "1.2.3.4:12345",
                                                                Account: &Account{
                                                                        Access: func() accessBitmap {
                                                                                var bits accessBitmap
-                                                                               bits.Set(accessGetClientInfo)
+                                                                               bits.Set(AccessGetClientInfo)
                                                                                return bits
                                                                        }(),
                                                                        Name:  "test",
                                                                        Login: "test",
                                                                },
                                                        },
-                                               },
-                                       },
-                                       transfers: map[int]map[[4]byte]*FileTransfer{
-                                               FileDownload:   {},
-                                               FileUpload:     {},
-                                               FolderDownload: {},
-                                               FolderUpload:   {},
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
+                                       ClientFileTransferMgr: ClientFileTransferMgr{},
                                },
                                t: NewTransaction(
                                        TranGetClientInfoText, [2]byte{0, 1},
@@ -2674,8 +2742,8 @@ func TestHandleTranAgreed(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessDisconUser)
-                                                       bits.Set(accessAnyName)
+                                                       bits.Set(AccessDisconUser)
+                                                       bits.Set(AccessAnyName)
                                                        return bits
                                                }()},
                                        Icon:    []byte{0, 1},
@@ -2684,9 +2752,20 @@ func TestHandleTranAgreed(t *testing.T) {
                                        ID:      [2]byte{0, 1},
                                        logger:  NewTestLogger(),
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        BannerFile: "banner.jpg",
                                                },
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               //{
+                                                               //      ID:       [2]byte{0, 2},
+                                                               //      UserName: []byte("UserB"),
+                                                               //},
+                                                       },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -2731,7 +2810,7 @@ func TestHandleSetClientUserInfo(t *testing.T) {
                wantRes []Transaction
        }{
                {
-                       name: "when client does not have accessAnyName",
+                       name: "when client does not have AccessAnyName",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
@@ -2744,11 +2823,15 @@ func TestHandleSetClientUserInfo(t *testing.T) {
                                        UserName: []byte("Guest"),
                                        Flags:    [2]byte{0, 1},
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 1}: {
-                                                               ID: [2]byte{0, 1},
-                                                       },
-                                               },
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               {
+                                                                       ID: [2]byte{0, 1},
+                                                               },
+                                                       })
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -2797,12 +2880,13 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        },
                                        ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
-                                                       "test": {
-                                                               Type: [2]byte{0, 3},
-                                                               Name: "zz",
-                                                       },
-                                               }},
+                                               ThreadedNewsMgr: func() *mockThreadNewsMgr {
+                                                       m := mockThreadNewsMgr{}
+                                                       m.On("NewsItem", []string{"test"}).Return(NewsCategoryListData15{
+                                                               Type: NewsCategory,
+                                                       })
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -2837,12 +2921,13 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        },
                                        ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
-                                                       "testcat": {
-                                                               Type: [2]byte{0, 2},
-                                                               Name: "test",
-                                                       },
-                                               }},
+                                               ThreadedNewsMgr: func() *mockThreadNewsMgr {
+                                                       m := mockThreadNewsMgr{}
+                                                       m.On("NewsItem", []string{"test"}).Return(NewsCategoryListData15{
+                                                               Type: NewsBundle,
+                                                       })
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -2875,24 +2960,18 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessNewsDeleteFldr)
+                                                       bits.Set(AccessNewsDeleteFldr)
                                                        return bits
                                                }(),
                                        },
                                        ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               ConfigDir: "/fakeConfigRoot",
-                                               FS: func() *MockFileStore {
-                                                       mfs := &MockFileStore{}
-                                                       mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
-                                                       return mfs
+                                               ThreadedNewsMgr: func() *mockThreadNewsMgr {
+                                                       m := mockThreadNewsMgr{}
+                                                       m.On("NewsItem", []string{"test"}).Return(NewsCategoryListData15{Type: NewsBundle})
+                                                       m.On("DeleteNewsItem", []string{"test"}).Return(nil)
+                                                       return &m
                                                }(),
-                                               ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
-                                                       "testcat": {
-                                                               Type: [2]byte{0, 2},
-                                                               Name: "test",
-                                                       },
-                                               }},
                                        },
                                },
                                t: NewTransaction(
@@ -2940,10 +3019,7 @@ func TestHandleTranOldPostNews(t *testing.T) {
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
-                                               Access: func() accessBitmap {
-                                                       var bits accessBitmap
-                                                       return bits
-                                               }(),
+                                               Access: accessBitmap{},
                                        },
                                },
                                t: NewTransaction(
@@ -2968,18 +3044,29 @@ func TestHandleTranOldPostNews(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessNewsPostArt)
+                                                       bits.Set(AccessNewsPostArt)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               FS: func() *MockFileStore {
-                                                       mfs := &MockFileStore{}
-                                                       mfs.On("WriteFile", "/fakeConfigRoot/MessageBoard.txt", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
-                                                       return mfs
+                                               Config: Config{
+                                                       NewsDateFormat: "",
+                                               },
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{})
+                                                       return &m
+                                               }(),
+                                               MessageBoard: func() *mockReadWriteSeeker {
+                                                       m := mockReadWriteSeeker{}
+                                                       m.On("Seek", int64(0), 0).Return(int64(0), nil)
+                                                       m.On("Read", mock.AnythingOfType("[]uint8")).Run(func(args mock.Arguments) {
+                                                               arg := args.Get(0).([]uint8)
+                                                               copy(arg, "TEST")
+                                                       }).Return(4, io.EOF)
+                                                       m.On("Write", mock.AnythingOfType("[]uint8")).Return(3, nil)
+                                                       return &m
                                                }(),
-                                               ConfigDir: "/fakeConfigRoot",
-                                               Config:    &Config{},
                                        },
                                },
                                t: NewTransaction(
@@ -3044,7 +3131,7 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessOpenChat)
+                                                       bits.Set(AccessOpenChat)
                                                        return bits
                                                }(),
                                        },
@@ -3052,13 +3139,19 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        Icon:     []byte{0, 1},
                                        Flags:    [2]byte{0, 0},
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 2}: {
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("Get", ClientID{0x0, 0x2}).Return(&ClientConn{
                                                                ID:       [2]byte{0, 2},
                                                                UserName: []byte("UserB"),
-                                                       },
-                                               },
-                                               PrivateChats: make(map[[4]byte]*PrivateChat),
+                                                       })
+                                                       return &m
+                                               }(),
+                                               ChatMgr: func() *MockChatManager {
+                                                       m := MockChatManager{}
+                                                       m.On("New", mock.AnythingOfType("*hotline.ClientConn")).Return(ChatID{0x52, 0xfd, 0xfc, 0x07})
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -3076,7 +3169,6 @@ func TestHandleInviteNewChat(t *testing.T) {
                                                NewField(FieldUserID, []byte{0, 1}),
                                        },
                                },
-
                                {
                                        clientID: [2]byte{0, 1},
                                        IsReply:  0x01,
@@ -3098,7 +3190,7 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessOpenChat)
+                                                       bits.Set(AccessOpenChat)
                                                        return bits
                                                }(),
                                        },
@@ -3106,14 +3198,21 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        Icon:     []byte{0, 1},
                                        Flags:    [2]byte{0, 0},
                                        Server: &Server{
-                                               Clients: map[[2]byte]*ClientConn{
-                                                       [2]byte{0, 2}: {
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("Get", ClientID{0, 2}).Return(&ClientConn{
                                                                ID:       [2]byte{0, 2},
+                                                               Icon:     []byte{0, 1},
                                                                UserName: []byte("UserB"),
                                                                Flags:    [2]byte{255, 255},
-                                                       },
-                                               },
-                                               PrivateChats: make(map[[4]byte]*PrivateChat),
+                                                       })
+                                                       return &m
+                                               }(),
+                                               ChatMgr: func() *MockChatManager {
+                                                       m := MockChatManager{}
+                                                       m.On("New", mock.AnythingOfType("*hotline.ClientConn")).Return(ChatID{0x52, 0xfd, 0xfc, 0x07})
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
@@ -3148,6 +3247,7 @@ func TestHandleInviteNewChat(t *testing.T) {
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
+
                        gotRes := HandleInviteNewChat(tt.args.cc, &tt.args.t)
 
                        tranAssertEqual(t, tt.wantRes, gotRes)
@@ -3167,28 +3267,73 @@ func TestHandleGetNewsArtData(t *testing.T) {
        }{
                {
                        name: "when user does not have required permission",
+                       args: args{
+                               cc: &ClientConn{Account: &Account{}},
+                               t: NewTransaction(
+                                       TranGetNewsArtData, [2]byte{0, 1},
+                               ),
+                       },
+                       wantRes: []Transaction{
+                               {
+                                       IsReply:   0x01,
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
+                                       Fields: []Field{
+                                               NewField(FieldError, []byte("You are not allowed to read news.")),
+                                       },
+                               },
+                       },
+               },
+               {
+                       name: "when user has required permission",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
+                                                       bits.Set(AccessNewsReadArt)
                                                        return bits
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               ThreadedNewsMgr: func() *mockThreadNewsMgr {
+                                                       m := mockThreadNewsMgr{}
+                                                       m.On("GetArticle", []string{"Example Category"}, uint32(1)).Return(&NewsArtData{
+                                                               Title:         "title",
+                                                               Poster:        "poster",
+                                                               Date:          [8]byte{},
+                                                               PrevArt:       [4]byte{0, 0, 0, 1},
+                                                               NextArt:       [4]byte{0, 0, 0, 2},
+                                                               ParentArt:     [4]byte{0, 0, 0, 3},
+                                                               FirstChildArt: [4]byte{0, 0, 0, 4},
+                                                               DataFlav:      []byte("text/plain"),
+                                                               Data:          "article data",
+                                                       })
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
                                        TranGetNewsArtData, [2]byte{0, 1},
+                                       NewField(FieldNewsPath, []byte{
+                                               // Example Category
+                                               0x00, 0x01, 0x00, 0x00, 0x10, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79,
+                                       }),
+                                       NewField(FieldNewsArtID, []byte{0, 1}),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       IsReply:   0x01,
-                                       ErrorCode: [4]byte{0, 0, 0, 1},
+                                       IsReply: 1,
                                        Fields: []Field{
-                                               NewField(FieldError, []byte("You are not allowed to read news.")),
+                                               NewField(FieldNewsArtTitle, []byte("title")),
+                                               NewField(FieldNewsArtPoster, []byte("poster")),
+                                               NewField(FieldNewsArtDate, []byte{0, 0, 0, 0, 0, 0, 0, 0}),
+                                               NewField(FieldNewsArtPrevArt, []byte{0, 0, 0, 1}),
+                                               NewField(FieldNewsArtNextArt, []byte{0, 0, 0, 2}),
+                                               NewField(FieldNewsArtParentArt, []byte{0, 0, 0, 3}),
+                                               NewField(FieldNewsArt1stChildArt, []byte{0, 0, 0, 4}),
+                                               NewField(FieldNewsArtDataFlav, []byte("text/plain")),
+                                               NewField(FieldNewsArtData, []byte("article data")),
                                        },
                                },
                        },
@@ -3223,7 +3368,7 @@ func TestHandleGetNewsArtNameList(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -3242,74 +3387,54 @@ func TestHandleGetNewsArtNameList(t *testing.T) {
                                },
                        },
                },
-               {
-                       name: "when user has required access",
-                       args: args{
-                               cc: &ClientConn{
-                                       Account: &Account{
-                                               Access: func() accessBitmap {
-                                                       var bits accessBitmap
-                                                       bits.Set(accessNewsReadArt)
-                                                       return bits
-                                               }(),
-                                       },
-                                       Server: &Server{
-                                               ThreadedNews: &ThreadedNews{
-                                                       Categories: map[string]NewsCategoryListData15{
-                                                               "Example Category": {
-                                                                       Type: [2]byte{0, 2},
-                                                                       Name: "",
-                                                                       Articles: map[uint32]*NewsArtData{
-                                                                               uint32(1): {
-                                                                                       Title:  "testTitle",
-                                                                                       Poster: "testPoster",
-                                                                                       Data:   "testBody",
-                                                                               },
-                                                                       },
-                                                                       SubCats:  nil,
-                                                                       GUID:     [16]byte{},
-                                                                       AddSN:    [4]byte{},
-                                                                       DeleteSN: [4]byte{},
-                                                               },
-                                                       },
-                                               },
-
-                                               //Accounts: map[string]*Account{
-                                               //      "guest": {
-                                               //              Name:     "guest",
-                                               //              Login:    "guest",
-                                               //              Password: "zz",
-                                               //              Access:   accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
-                                               //      },
-                                               //},
-                                       },
-                               },
-                               t: NewTransaction(
-                                       TranGetNewsArtNameList,
-                                       [2]byte{0, 1},
-                                       //  00000000  00 01 00 00 10 45 78 61  6d 70 6c 65 20 43 61 74  |.....Example Cat|
-                                       //  00000010  65 67 6f 72 79                                    |egory|
-                                       NewField(FieldNewsPath, []byte{
-                                               0x00, 0x01, 0x00, 0x00, 0x10, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79,
-                                       }),
-                               ),
-                       },
-                       wantRes: []Transaction{
-                               {
-                                       IsReply: 0x01,
-                                       Fields: []Field{
-                                               NewField(FieldNewsArtListData, []byte{
-                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
-                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-                                                       0x09, 0x74, 0x65, 0x73, 0x74, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x50,
-                                                       0x6f, 0x73, 0x74, 0x65, 0x72, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e,
-                                                       0x00, 0x08,
-                                               },
-                                               ),
-                                       },
-                               },
-                       },
-               },
+               //{
+               //      name: "when user has required access",
+               //      args: args{
+               //              cc: &ClientConn{
+               //                      Account: &Account{
+               //                              Access: func() accessBitmap {
+               //                                      var bits accessBitmap
+               //                                      bits.Set(AccessNewsReadArt)
+               //                                      return bits
+               //                              }(),
+               //                      },
+               //                      Server: &Server{
+               //                              ThreadedNewsMgr: func() *mockThreadNewsMgr {
+               //                                      m := mockThreadNewsMgr{}
+               //                                      m.On("ListArticles", []string{"Example Category"}).Return(NewsArtListData{
+               //                                              Name:        []byte("testTitle"),
+               //                                              NewsArtList: []byte{},
+               //                                      })
+               //                                      return &m
+               //                              }(),
+               //                      },
+               //              },
+               //              t: NewTransaction(
+               //                      TranGetNewsArtNameList,
+               //                      [2]byte{0, 1},
+               //                      //  00000000  00 01 00 00 10 45 78 61  6d 70 6c 65 20 43 61 74  |.....Example Cat|
+               //                      //  00000010  65 67 6f 72 79                                    |egory|
+               //                      NewField(FieldNewsPath, []byte{
+               //                              0x00, 0x01, 0x00, 0x00, 0x10, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79,
+               //                      }),
+               //              ),
+               //      },
+               //      wantRes: []Transaction{
+               //              {
+               //                      IsReply: 0x01,
+               //                      Fields: []Field{
+               //                              NewField(FieldNewsArtListData, []byte{
+               //                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+               //                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+               //                                      0x09, 0x74, 0x65, 0x73, 0x74, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x50,
+               //                                      0x6f, 0x73, 0x74, 0x65, 0x72, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e,
+               //                                      0x00, 0x08,
+               //                              },
+               //                              ),
+               //                      },
+               //              },
+               //      },
+               //},
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
@@ -3341,7 +3466,7 @@ func TestHandleNewNewsFldr(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
@@ -3367,26 +3492,18 @@ func TestHandleNewNewsFldr(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessNewsCreateFldr)
+                                                       bits.Set(AccessNewsCreateFldr)
                                                        return bits
                                                }(),
                                        },
                                        logger: NewTestLogger(),
                                        ID:     [2]byte{0, 1},
                                        Server: &Server{
-                                               ConfigDir: "/fakeConfigRoot",
-                                               FS: func() *MockFileStore {
-                                                       mfs := &MockFileStore{}
-                                                       mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(nil)
-                                                       return mfs
+                                               ThreadedNewsMgr: func() *mockThreadNewsMgr {
+                                                       m := mockThreadNewsMgr{}
+                                                       m.On("CreateGrouping", []string{"test"}, "testFolder", NewsBundle).Return(nil)
+                                                       return &m
                                                }(),
-                                               ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
-                                                       "test": {
-                                                               Type:    [2]byte{0, 2},
-                                                               Name:    "test",
-                                                               SubCats: make(map[string]NewsCategoryListData15),
-                                                       },
-                                               }},
                                        },
                                },
                                t: NewTransaction(
@@ -3417,12 +3534,12 @@ func TestHandleNewNewsFldr(t *testing.T) {
                //                      Account: &Account{
                //                              Access: func() accessBitmap {
                //                                      var bits accessBitmap
-               //                                      bits.Set(accessNewsCreateFldr)
+               //                                      bits.Set(AccessNewsCreateFldr)
                //                                      return bits
                //                              }(),
                //                      },
                //                      logger: NewTestLogger(),
-               //                      ID:     [2]byte{0, 1},
+               //                      Type:     [2]byte{0, 1},
                //                      Server: &Server{
                //                              ConfigDir: "/fakeConfigRoot",
                //                              FS: func() *MockFileStore {
@@ -3538,32 +3655,16 @@ func TestHandlePostNewsArt(t *testing.T) {
                        args: args{
                                cc: &ClientConn{
                                        Server: &Server{
-                                               FS: func() *MockFileStore {
-                                                       mfs := &MockFileStore{}
-                                                       mfs.On("WriteFile", "ThreadedNews.yaml", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
-                                                       return mfs
+                                               ThreadedNewsMgr: func() *mockThreadNewsMgr {
+                                                       m := mockThreadNewsMgr{}
+                                                       m.On("PostArticle", []string{"www"}, uint32(0), mock.AnythingOfType("hotline.NewsArtData")).Return(nil)
+                                                       return &m
                                                }(),
-                                               mux:             sync.Mutex{},
-                                               threadedNewsMux: sync.Mutex{},
-                                               ThreadedNews: &ThreadedNews{
-                                                       Categories: map[string]NewsCategoryListData15{
-                                                               "www": {
-                                                                       Type:       [2]byte{},
-                                                                       Name:       "www",
-                                                                       Articles:   map[uint32]*NewsArtData{},
-                                                                       SubCats:    nil,
-                                                                       GUID:       [16]byte{},
-                                                                       AddSN:      [4]byte{},
-                                                                       DeleteSN:   [4]byte{},
-                                                                       readOffset: 0,
-                                                               },
-                                                       },
-                                               },
                                        },
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessNewsPostArt)
+                                                       bits.Set(AccessNewsPostArt)
                                                        return bits
                                                }(),
                                        },