]> git.r.bdr.sh - rbdr/mobius/blobdiff - hotline/transaction_handlers_test.go
Delete docs/Screenshot 2024-05-03 at 4.40.09 PM.png
[rbdr/mobius] / hotline / transaction_handlers_test.go
index 81ba6e0f5b81afca2cba93a678d54b8cfceaabc1..610e11399f7516467b844f0fe053598cc5596f76 100644 (file)
@@ -2,12 +2,10 @@ package hotline
 
 import (
        "errors"
-       "fmt"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/mock"
        "io"
        "io/fs"
-       "math/rand"
        "os"
        "path/filepath"
        "strings"
@@ -18,13 +16,12 @@ import (
 func TestHandleSetChatSubject(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
-               name    string
-               args    args
-               want    []Transaction
-               wantErr bool
+               name string
+               args args
+               want []Transaction
        }{
                {
                        name: "sends chat subject to private chat members",
@@ -32,47 +29,68 @@ func TestHandleSetChatSubject(t *testing.T) {
                                cc: &ClientConn{
                                        UserName: []byte{0x00, 0x01},
                                        Server: &Server{
-                                               PrivateChats: map[uint32]*PrivateChat{
-                                                       uint32(1): {
-                                                               Subject: "unset",
-                                                               ClientConn: map[uint16]*ClientConn{
-                                                                       uint16(1): {
-                                                                               Account: &Account{
-                                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
-                                                                               },
-                                                                               ID: &[]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},
                                                                        },
-                                                                       uint16(2): {
-                                                                               Account: &Account{
-                                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
-                                                                               },
-                                                                               ID: &[]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[uint16]*ClientConn{
-                                                       uint16(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: &[]byte{0, 1},
-                                                       },
-                                                       uint16(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: &[]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
-                               t: &Transaction{
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0, 0, 0, 1},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                               t: Transaction{
+                                       Type: [2]byte{0, 0x6a},
+                                       ID:   [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldChatID, []byte{0, 0, 0, 1}),
                                                NewField(FieldChatSubject, []byte("Test Subject")),
@@ -81,43 +99,28 @@ func TestHandleSetChatSubject(t *testing.T) {
                        },
                        want: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x77},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Type:     [2]byte{0, 0x77},
                                        Fields: []Field{
                                                NewField(FieldChatID, []byte{0, 0, 0, 1}),
                                                NewField(FieldChatSubject, []byte("Test Subject")),
                                        },
                                },
                                {
-                                       clientID:  &[]byte{0, 2},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x77},
-                                       ID:        []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 2},
+                                       Type:     [2]byte{0, 0x77},
                                        Fields: []Field{
                                                NewField(FieldChatID, []byte{0, 0, 0, 1}),
                                                NewField(FieldChatSubject, []byte("Test Subject")),
                                        },
                                },
                        },
-                       wantErr: false,
                },
        }
        for _, tt := range tests {
-               rand.Seed(1) // reset seed between tests to make transaction IDs predictable
-
                t.Run(tt.name, func(t *testing.T) {
-                       got, err := HandleSetChatSubject(tt.args.cc, tt.args.t)
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("HandleSetChatSubject() error = %v, wantErr %v", err, tt.wantErr)
-                               return
-                       }
-                       if !assert.Equal(t, tt.want, got) {
+                       got := HandleSetChatSubject(tt.args.cc, &tt.args.t)
+                       if !tranAssertEqual(t, tt.want, got) {
                                t.Errorf("HandleSetChatSubject() got = %v, want %v", got, tt.want)
                        }
                })
@@ -127,82 +130,72 @@ func TestHandleSetChatSubject(t *testing.T) {
 func TestHandleLeaveChat(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
-               name    string
-               args    args
-               want    []Transaction
-               wantErr bool
+               name string
+               args args
+               want []Transaction
        }{
                {
-                       name: "returns expected transactions",
+                       name: "when client 2 leaves chat",
                        args: args{
                                cc: &ClientConn{
-                                       ID: &[]byte{0, 2},
+                                       ID: [2]byte{0, 2},
                                        Server: &Server{
-                                               PrivateChats: map[uint32]*PrivateChat{
-                                                       uint32(1): {
-                                                               ClientConn: map[uint16]*ClientConn{
-                                                                       uint16(1): {
-                                                                               Account: &Account{
-                                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
-                                                                               },
-                                                                               ID: &[]byte{0, 1},
-                                                                       },
-                                                                       uint16(2): {
-                                                                               Account: &Account{
-                                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
-                                                                               },
-                                                                               ID: &[]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[uint16]*ClientConn{
-                                                       uint16(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: &[]byte{0, 1},
-                                                       },
-                                                       uint16(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: &[]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
-                               t: NewTransaction(TranDeleteUser, nil, NewField(FieldChatID, []byte{0, 0, 0, 1})),
+                               t: NewTransaction(TranDeleteUser, [2]byte{}, NewField(FieldChatID, []byte{0, 0, 0, 1})),
                        },
                        want: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x76},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Type:     [2]byte{0, 0x76},
                                        Fields: []Field{
                                                NewField(FieldChatID, []byte{0, 0, 0, 1}),
                                                NewField(FieldUserID, []byte{0, 2}),
                                        },
                                },
                        },
-                       wantErr: false,
                },
        }
        for _, tt := range tests {
-               rand.Seed(1)
                t.Run(tt.name, func(t *testing.T) {
-                       got, err := HandleLeaveChat(tt.args.cc, tt.args.t)
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("HandleLeaveChat() error = %v, wantErr %v", err, tt.wantErr)
-                               return
-                       }
-                       if !assert.Equal(t, tt.want, got) {
+                       got := HandleLeaveChat(tt.args.cc, &tt.args.t)
+                       if !tranAssertEqual(t, tt.want, got) {
                                t.Errorf("HandleLeaveChat() got = %v, want %v", got, tt.want)
                        }
                })
@@ -212,50 +205,46 @@ func TestHandleLeaveChat(t *testing.T) {
 func TestHandleGetUserNameList(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
-               name    string
-               args    args
-               want    []Transaction
-               wantErr bool
+               name string
+               args args
+               want []Transaction
        }{
                {
                        name: "replies with userlist transaction",
                        args: args{
                                cc: &ClientConn{
-
-                                       ID: &[]byte{1, 1},
+                                       ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Clients: map[uint16]*ClientConn{
-                                                       uint16(1): {
-                                                               ID:       &[]byte{0, 1},
-                                                               Icon:     []byte{0, 2},
-                                                               Flags:    []byte{0, 3},
-                                                               UserName: []byte{0, 4},
-                                                       },
-                                                       uint16(2): {
-                                                               ID:       &[]byte{0, 2},
-                                                               Icon:     []byte{0, 2},
-                                                               Flags:    []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{
-                                       ID:   []byte{0, 0, 0, 1},
-                                       Type: []byte{0, 1},
-                               },
+                               t: Transaction{},
                        },
                        want: []Transaction{
                                {
-                                       clientID:  &[]byte{1, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 1},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
                                        Fields: []Field{
                                                NewField(
                                                        FieldUsernameWithInfo,
@@ -268,16 +257,11 @@ func TestHandleGetUserNameList(t *testing.T) {
                                        },
                                },
                        },
-                       wantErr: false,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       got, err := HandleGetUserNameList(tt.args.cc, tt.args.t)
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("HandleGetUserNameList() error = %v, wantErr %v", err, tt.wantErr)
-                               return
-                       }
+                       got := HandleGetUserNameList(tt.args.cc, &tt.args.t)
                        assert.Equal(t, tt.want, got)
                })
        }
@@ -286,13 +270,12 @@ func TestHandleGetUserNameList(t *testing.T) {
 func TestHandleChatSend(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
-               name    string
-               args    args
-               want    []Transaction
-               wantErr bool
+               name string
+               args args
+               want []Transaction
        }{
                {
                        name: "sends chat msg transaction to all clients",
@@ -301,29 +284,34 @@ 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[uint16]*ClientConn{
-                                                       uint16(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: &[]byte{0, 1},
-                                                       },
-                                                       uint16(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: &[]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
-                               t: &Transaction{
+                               t: Transaction{
                                        Fields: []Field{
                                                NewField(FieldData, []byte("hai")),
                                        },
@@ -331,60 +319,60 @@ func TestHandleChatSend(t *testing.T) {
                        },
                        want: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Flags:    0x00,
+                                       IsReply:  0x00,
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                                {
-                                       clientID:  &[]byte{0, 2},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 2},
+                                       Flags:    0x00,
+                                       IsReply:  0x00,
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                        },
-                       wantErr: false,
                },
                {
-                       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[uint16]*ClientConn{
-                                                       uint16(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: &[]byte{0, 1},
-                                                       },
-                                                       uint16(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: &[]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
-                               t: &Transaction{
+                               t: Transaction{
                                        Fields: []Field{
                                                NewField(FieldData, []byte("hai")),
                                                NewField(FieldChatID, []byte{0, 0, 0, 0}),
@@ -393,29 +381,20 @@ func TestHandleChatSend(t *testing.T) {
                        },
                        want: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                                {
-                                       clientID:  &[]byte{0, 2},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 2},
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                        },
-                       wantErr: false,
                },
                {
                        name: "when user does not have required permission",
@@ -428,27 +407,23 @@ func TestHandleChatSend(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
-                                       TranChatSend, &[]byte{0, 1},
+                                       TranChatSend, [2]byte{0, 1},
                                        NewField(FieldData, []byte("hai")),
                                ),
                        },
                        want: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to participate in chat.")),
                                        },
                                },
                        },
-                       wantErr: false,
                },
                {
                        name: "sends chat msg as emote if FieldChatOptions is set to 1",
@@ -457,29 +432,34 @@ 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[uint16]*ClientConn{
-                                                       uint16(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: &[]byte{0, 1},
-                                                       },
-                                                       uint16(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: &[]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
-                               t: &Transaction{
+                               t: Transaction{
                                        Fields: []Field{
                                                NewField(FieldData, []byte("performed action")),
                                                NewField(FieldChatOptions, []byte{0x00, 0x01}),
@@ -488,29 +468,24 @@ func TestHandleChatSend(t *testing.T) {
                        },
                        want: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Flags:    0x00,
+                                       IsReply:  0x00,
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldData, []byte("\r*** Testy McTest performed action")),
                                        },
                                },
                                {
-                                       clientID:  &[]byte{0, 2},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0xf0, 0xc5, 0x34, 0x1e},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 2},
+                                       Flags:    0x00,
+                                       IsReply:  0x00,
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldData, []byte("\r*** Testy McTest performed action")),
                                        },
                                },
                        },
-                       wantErr: false,
                },
                {
                        name: "does not send chat msg as emote if FieldChatOptions is set to 0",
@@ -519,29 +494,34 @@ 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[uint16]*ClientConn{
-                                                       uint16(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: &[]byte{0, 1},
-                                                       },
-                                                       uint16(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: &[]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
-                               t: &Transaction{
+                               t: Transaction{
                                        Fields: []Field{
                                                NewField(FieldData, []byte("hello")),
                                                NewField(FieldChatOptions, []byte{0x00, 0x00}),
@@ -550,63 +530,58 @@ func TestHandleChatSend(t *testing.T) {
                        },
                        want: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldData, []byte("\r Testy McTest:  hello")),
                                        },
                                },
                                {
-                                       clientID:  &[]byte{0, 2},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0xf0, 0xc5, 0x34, 0x1e},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 2},
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldData, []byte("\r Testy McTest:  hello")),
                                        },
                                },
                        },
-                       wantErr: false,
                },
                {
-                       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[uint16]*ClientConn{
-                                                       uint16(1): {
-                                                               Account: &Account{
-                                                                       Access: func() accessBitmap {
-                                                                               var bits accessBitmap
-                                                                               bits.Set(accessReadChat)
-                                                                               return bits
-                                                                       }()},
-                                                               ID: &[]byte{0, 1},
-                                                       },
-                                                       uint16(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: &[]byte{0, 2},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
-                               t: &Transaction{
+                               t: Transaction{
                                        Fields: []Field{
                                                NewField(FieldData, []byte("hai")),
                                        },
@@ -614,18 +589,13 @@ func TestHandleChatSend(t *testing.T) {
                        },
                        want: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                        },
-                       wantErr: false,
                },
                {
                        name: "only sends private chat msg to members of private chat",
@@ -634,47 +604,53 @@ 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[uint32]*PrivateChat{
-                                                       uint32(1): {
-                                                               ClientConn: map[uint16]*ClientConn{
-                                                                       uint16(1): {
-                                                                               ID: &[]byte{0, 1},
-                                                                       },
-                                                                       uint16(2): {
-                                                                               ID: &[]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[uint16]*ClientConn{
-                                                       uint16(1): {
-                                                               Account: &Account{
-                                                                       Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+                                                               {
+                                                                       ID: [2]byte{0, 2},
                                                                },
-                                                               ID: &[]byte{0, 1},
-                                                       },
-                                                       uint16(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: &[]byte{0, 2},
-                                                       },
-                                                       uint16(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: &[]byte{0, 3},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
-                               t: &Transaction{
+                               t: Transaction{
                                        Fields: []Field{
                                                NewField(FieldData, []byte("hai")),
                                                NewField(FieldChatID, []byte{0, 0, 0, 1}),
@@ -683,67 +659,50 @@ func TestHandleChatSend(t *testing.T) {
                        },
                        want: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldChatID, []byte{0, 0, 0, 1}),
                                                NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                                {
-                                       clientID:  &[]byte{0, 2},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x6a},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 2},
+                                       Type:     [2]byte{0, 0x6a},
                                        Fields: []Field{
                                                NewField(FieldChatID, []byte{0, 0, 0, 1}),
                                                NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
                                        },
                                },
                        },
-                       wantErr: false,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       got, err := HandleChatSend(tt.args.cc, tt.args.t)
-
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("HandleChatSend() error = %v, wantErr %v", err, tt.wantErr)
-                               return
-                       }
+                       got := HandleChatSend(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.want, got)
                })
        }
 }
 
 func TestHandleGetFileInfo(t *testing.T) {
-       rand.Seed(1) // reset seed between tests to make transaction IDs predictable
-
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr bool
        }{
                {
                        name: "returns expected fields when a valid file is requested",
                        args: args{
                                cc: &ClientConn{
-                                       ID: &[]byte{0x00, 0x01},
+                                       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")
@@ -752,19 +711,16 @@ func TestHandleGetFileInfo(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranGetFileInfo, nil,
+                                       TranGetFileInfo, [2]byte{},
                                        NewField(FieldFileName, []byte("testfile.txt")),
                                        NewField(FieldFilePath, []byte{0x00, 0x00}),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
+                                       Type:     [2]byte{0, 0},
                                        Fields: []Field{
                                                NewField(FieldFileName, []byte("testfile.txt")),
                                                NewField(FieldFileTypeString, []byte("Text File")),
@@ -776,24 +732,18 @@ func TestHandleGetFileInfo(t *testing.T) {
                                        },
                                },
                        },
-                       wantErr: false,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       rand.Seed(1) // reset seed between tests to make transaction IDs predictable
-
-                       gotRes, err := HandleGetFileInfo(tt.args.cc, tt.args.t)
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("HandleGetFileInfo() error = %v, wantErr %v", err, tt.wantErr)
-                               return
-                       }
+                       gotRes := HandleGetFileInfo(tt.args.cc, &tt.args.t)
 
-                       // Clear the fileWrapper timestamp fields to work around problems running the tests in multiple timezones
+                       // Clear the file timestamp fields to work around problems running the tests in multiple timezones
                        // TODO: revisit how to test this by mocking the stat calls
                        gotRes[0].Fields[4].Data = make([]byte, 8)
                        gotRes[0].Fields[5].Data = make([]byte, 8)
-                       if !assert.Equal(t, tt.wantRes, gotRes) {
+
+                       if !tranAssertEqual(t, tt.wantRes, gotRes) {
                                t.Errorf("HandleGetFileInfo() gotRes = %v, want %v", gotRes, tt.wantRes)
                        }
                })
@@ -803,13 +753,12 @@ func TestHandleGetFileInfo(t *testing.T) {
 func TestHandleNewFolder(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr bool
        }{
                {
                        name: "without required permission",
@@ -823,23 +772,19 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       accessCreateFolder,
-                                       &[]byte{0, 0},
+                                       TranNewFolder,
+                                       [2]byte{0, 0},
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to create folders.")),
                                        },
                                },
                        },
-                       wantErr: false,
                },
                {
                        name: "when path is nested",
@@ -848,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: &[]byte{0, 1},
+                                       ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: "/Files/",
                                                },
                                                FS: func() *MockFileStore {
@@ -866,7 +811,7 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranNewFolder, &[]byte{0, 1},
+                                       TranNewFolder, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testFolder")),
                                        NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
@@ -878,15 +823,10 @@ func TestHandleNewFolder(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
                                },
                        },
-                       wantErr: false,
                },
                {
                        name: "when path is not nested",
@@ -895,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: &[]byte{0, 1},
+                                       ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: "/Files",
                                                },
                                                FS: func() *MockFileStore {
@@ -913,21 +853,16 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranNewFolder, &[]byte{0, 1},
+                                       TranNewFolder, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testFolder")),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
                                },
                        },
-                       wantErr: false,
                },
                {
                        name: "when Write returns an err",
@@ -936,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: &[]byte{0, 1},
+                                       ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: "/Files/",
                                                },
                                                FS: func() *MockFileStore {
@@ -954,7 +889,7 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranNewFolder, &[]byte{0, 1},
+                                       TranNewFolder, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testFolder")),
                                        NewField(FieldFilePath, []byte{
                                                0x00,
@@ -962,7 +897,6 @@ func TestHandleNewFolder(t *testing.T) {
                                ),
                        },
                        wantRes: []Transaction{},
-                       wantErr: true,
                },
                {
                        name: "FieldFileName does not allow directory traversal",
@@ -971,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: &[]byte{0, 1},
+                                       ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: "/Files/",
                                                },
                                                FS: func() *MockFileStore {
@@ -989,20 +923,16 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranNewFolder, &[]byte{0, 1},
+                                       TranNewFolder, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("../../testFolder")),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
                                },
-                       }, wantErr: false,
+                       },
                },
                {
                        name: "FieldFilePath does not allow directory traversal",
@@ -1011,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: &[]byte{0, 1},
+                                       ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: "/Files/",
                                                },
                                                FS: func() *MockFileStore {
@@ -1029,7 +959,7 @@ func TestHandleNewFolder(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranNewFolder, &[]byte{0, 1},
+                                       TranNewFolder, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testFolder")),
                                        NewField(FieldFilePath, []byte{
                                                0x00, 0x02,
@@ -1044,23 +974,15 @@ func TestHandleNewFolder(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
                                },
-                       }, wantErr: false,
+                       },
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleNewFolder(tt.args.cc, tt.args.t)
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("HandleNewFolder() error = %v, wantErr %v", err, tt.wantErr)
-                               return
-                       }
+                       gotRes := HandleNewFolder(tt.args.cc, &tt.args.t)
 
                        if !tranAssertEqual(t, tt.wantRes, gotRes) {
                                t.Errorf("HandleNewFolder() gotRes = %v, want %v", gotRes, tt.wantRes)
@@ -1072,38 +994,35 @@ func TestHandleNewFolder(t *testing.T) {
 func TestHandleUploadFile(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr bool
        }{
                {
                        name: "when request is valid and user has Upload Anywhere permission",
                        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
                                                }(),
                                        },
                                },
                                t: NewTransaction(
-                                       TranUploadFile, &[]byte{0, 1},
+                                       TranUploadFile, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testFile")),
                                        NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
@@ -1115,17 +1034,12 @@ func TestHandleUploadFile(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       IsReply: 0x01,
                                        Fields: []Field{
                                                NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}), // rand.Seed(1)
                                        },
                                },
                        },
-                       wantErr: false,
                },
                {
                        name: "when user does not have required access",
@@ -1139,7 +1053,7 @@ func TestHandleUploadFile(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranUploadFile, &[]byte{0, 1},
+                                       TranUploadFile, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testFile")),
                                        NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
@@ -1151,28 +1065,18 @@ func TestHandleUploadFile(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to upload files.")), // rand.Seed(1)
                                        },
                                },
                        },
-                       wantErr: false,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       rand.Seed(1)
-                       gotRes, err := HandleUploadFile(tt.args.cc, tt.args.t)
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("HandleUploadFile() error = %v, wantErr %v", err, tt.wantErr)
-                               return
-                       }
-
+                       gotRes := HandleUploadFile(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -1181,13 +1085,12 @@ func TestHandleUploadFile(t *testing.T) {
 func TestHandleMakeAlias(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr bool
        }{
                {
                        name: "with valid input and required permissions",
@@ -1197,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"
@@ -1222,7 +1125,7 @@ func TestHandleMakeAlias(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranMakeFileAlias, &[]byte{0, 1},
+                                       TranMakeFileAlias, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testFile")),
                                        NewField(FieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
                                        NewField(FieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
@@ -1230,15 +1133,10 @@ func TestHandleMakeAlias(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
-                                       Fields:    []Field(nil),
+                                       IsReply: 0x01,
+                                       Fields:  []Field(nil),
                                },
                        },
-                       wantErr: false,
                },
                {
                        name: "when symlink returns an error",
@@ -1248,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"
@@ -1273,7 +1171,7 @@ func TestHandleMakeAlias(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranMakeFileAlias, &[]byte{0, 1},
+                                       TranMakeFileAlias, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testFile")),
                                        NewField(FieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
                                        NewField(FieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
@@ -1281,17 +1179,13 @@ func TestHandleMakeAlias(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("Error creating alias")),
                                        },
                                },
                        },
-                       wantErr: false,
                },
                {
                        name: "when user does not have required permission",
@@ -1299,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"
@@ -1314,7 +1205,7 @@ func TestHandleMakeAlias(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranMakeFileAlias, &[]byte{0, 1},
+                                       TranMakeFileAlias, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testFile")),
                                        NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
@@ -1332,27 +1223,18 @@ func TestHandleMakeAlias(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to make aliases.")),
                                        },
                                },
                        },
-                       wantErr: false,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleMakeAlias(tt.args.cc, tt.args.t)
-                       if (err != nil) != tt.wantErr {
-                               t.Errorf("HandleMakeAlias(%v, %v)", tt.args.cc, tt.args.t)
-                               return
-                       }
-
+                       gotRes := HandleMakeAlias(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -1361,13 +1243,12 @@ func TestHandleMakeAlias(t *testing.T) {
 func TestHandleGetUser(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when account is valid",
@@ -1376,33 +1257,31 @@ 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(
-                                       TranGetUser, &[]byte{0, 1},
+                                       TranGetUser, [2]byte{0, 1},
                                        NewField(FieldUserLogin, []byte("guest")),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       IsReply: 0x01,
                                        Fields: []Field{
                                                NewField(FieldUserName, []byte("Guest")),
                                                NewField(FieldUserLogin, encodeString([]byte("guest"))),
@@ -1411,7 +1290,6 @@ func TestHandleGetUser(t *testing.T) {
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when user does not have required permission",
@@ -1424,27 +1302,23 @@ func TestHandleGetUser(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
-                                       TranGetUser, &[]byte{0, 1},
+                                       TranGetUser, [2]byte{0, 1},
                                        NewField(FieldUserLogin, []byte("nonExistentUser")),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to view accounts.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when account does not exist",
@@ -1453,16 +1327,20 @@ 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(
-                                       TranGetUser, &[]byte{0, 1},
+                                       TranGetUser, [2]byte{0, 1},
                                        NewField(FieldUserLogin, []byte("nonExistentUser")),
                                ),
                        },
@@ -1470,24 +1348,18 @@ func TestHandleGetUser(t *testing.T) {
                                {
                                        Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       Type:      [2]byte{0, 0},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("Account does not exist.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleGetUser(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleGetUser(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
-
+                       gotRes := HandleGetUser(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -1496,99 +1368,81 @@ func TestHandleGetUser(t *testing.T) {
 func TestHandleDeleteUser(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
-                       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
                                                }(),
                                        },
                                },
                                t: NewTransaction(
-                                       TranDeleteUser, &[]byte{0, 1},
+                                       TranDeleteUser, [2]byte{0, 1},
                                        NewField(FieldUserLogin, encodeString([]byte("testuser"))),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
-                                       Fields:    []Field(nil),
+                                       Flags:   0x00,
+                                       IsReply: 0x01,
+                                       Type:    [2]byte{0, 0},
+                                       Fields:  []Field(nil),
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when user does not have required permission",
                        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(
-                                       TranDeleteUser, &[]byte{0, 1},
+                                       TranDeleteUser, [2]byte{0, 1},
                                        NewField(FieldUserLogin, encodeString([]byte("testuser"))),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to delete accounts.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleDeleteUser(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleDeleteUser(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
-
+                       gotRes := HandleDeleteUser(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -1597,13 +1451,12 @@ func TestHandleDeleteUser(t *testing.T) {
 func TestHandleGetMsgs(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "returns news data",
@@ -1612,72 +1465,64 @@ 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(
-                                       TranGetMsgs, &[]byte{0, 1},
+                                       TranGetMsgs, [2]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       IsReply: 0x01,
                                        Fields: []Field{
                                                NewField(FieldData, []byte("TEST")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when user does not have required permission",
                        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(
-                                       TranGetMsgs, &[]byte{0, 1},
+                                       TranGetMsgs, [2]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to read news.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleGetMsgs(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleGetMsgs(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
-
+                       gotRes := HandleGetMsgs(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -1686,13 +1531,12 @@ func TestHandleGetMsgs(t *testing.T) {
 func TestHandleNewUser(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when user does not have required permission",
@@ -1705,26 +1549,22 @@ func TestHandleNewUser(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
-                                       TranNewUser, &[]byte{0, 1},
+                                       TranNewUser, [2]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to create new accounts.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when user attempts to create account with greater access",
@@ -1733,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, &[]byte{0, 1},
-                                       NewField(FieldUserLogin, []byte("userB")),
+                                       TranNewUser, [2]byte{0, 1},
+                                       NewField(FieldUserLogin, encodeString([]byte("userB"))),
                                        NewField(
                                                FieldUserAccess,
                                                func() []byte {
                                                        var bits accessBitmap
-                                                       bits.Set(accessDisconUser)
+                                                       bits.Set(AccessDisconUser)
                                                        return bits[:]
                                                }(),
                                        ),
@@ -1756,26 +1600,18 @@ func TestHandleNewUser(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("Cannot create account with more access than yourself.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleNewUser(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleNewUser(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
-
+                       gotRes := HandleNewUser(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -1784,13 +1620,12 @@ func TestHandleNewUser(t *testing.T) {
 func TestHandleListUsers(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when user does not have required permission",
@@ -1803,26 +1638,22 @@ func TestHandleListUsers(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
-                                       TranNewUser, &[]byte{0, 1},
+                                       TranNewUser, [2]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to view accounts.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when user has required permission",
@@ -1831,33 +1662,33 @@ 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(
-                                       TranGetClientInfoText, &[]byte{0, 1},
+                                       TranGetClientInfoText, [2]byte{0, 1},
                                        NewField(FieldUserID, []byte{0, 1}),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       IsReply: 0x01,
                                        Fields: []Field{
                                                NewField(FieldData, []byte{
                                                        0x00, 0x04, 0x00, 0x66, 0x00, 0x05, 0x67, 0x75, 0x65, 0x73, 0x74, 0x00, 0x69, 0x00, 0x05, 0x98,
@@ -1867,15 +1698,11 @@ func TestHandleListUsers(t *testing.T) {
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleListUsers(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleListUsers(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+                       gotRes := HandleListUsers(tt.args.cc, &tt.args.t)
 
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
@@ -1885,13 +1712,12 @@ func TestHandleListUsers(t *testing.T) {
 func TestHandleDownloadFile(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when user does not have required permission",
@@ -1905,59 +1731,48 @@ func TestHandleDownloadFile(t *testing.T) {
                                        },
                                        Server: &Server{},
                                },
-                               t: NewTransaction(TranDownloadFile, &[]byte{0, 1}),
+                               t: NewTransaction(TranDownloadFile, [2]byte{0, 1}),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to download files.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        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(
-                                       accessDownloadFile,
-                                       &[]byte{0, 1},
+                                       TranDownloadFile,
+                                       [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testfile.txt")),
                                        NewField(FieldFilePath, []byte{0x0, 0x00}),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       IsReply: 0x01,
                                        Fields: []Field{
                                                NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
                                                NewField(FieldWaitingCount, []byte{0x00, 0x00}),
@@ -1966,18 +1781,16 @@ func TestHandleDownloadFile(t *testing.T) {
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        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
                                                }(),
                                        },
@@ -2001,38 +1814,31 @@ 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(
-                                       accessDownloadFile,
-                                       &[]byte{0, 1},
+                                       TranDownloadFile,
+                                       [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testfile-1k")),
                                        NewField(FieldFilePath, []byte{0x00, 0x00}),
                                        NewField(
                                                FieldFileResumeData,
                                                func() []byte {
                                                        frd := FileResumeData{
-                                                               Format:    [4]byte{},
-                                                               Version:   [2]byte{},
-                                                               RSVD:      [34]byte{},
                                                                ForkCount: [2]byte{0, 2},
                                                                ForkInfoList: []ForkInfoList{
                                                                        {
                                                                                Fork:     [4]byte{0x44, 0x41, 0x54, 0x41}, // "DATA"
                                                                                DataSize: [4]byte{0, 0, 0x01, 0x00},       // request offset 256
-                                                                               RSVDA:    [4]byte{},
-                                                                               RSVDB:    [4]byte{},
                                                                        },
                                                                        {
                                                                                Fork:     [4]byte{0x4d, 0x41, 0x43, 0x52}, // "MACR"
                                                                                DataSize: [4]byte{0, 0, 0, 0},
-                                                                               RSVDA:    [4]byte{},
-                                                                               RSVDB:    [4]byte{},
                                                                        },
                                                                },
                                                        }
@@ -2044,11 +1850,7 @@ func TestHandleDownloadFile(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       IsReply: 0x01,
                                        Fields: []Field{
                                                NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
                                                NewField(FieldWaitingCount, []byte{0x00, 0x00}),
@@ -2057,16 +1859,11 @@ func TestHandleDownloadFile(t *testing.T) {
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleDownloadFile(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleDownloadFile(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
-
+                       gotRes := HandleDownloadFile(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -2075,13 +1872,12 @@ func TestHandleDownloadFile(t *testing.T) {
 func TestHandleUpdateUser(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when action is create user without required permission",
@@ -2089,18 +1885,20 @@ 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(
                                        TranUpdateUser,
-                                       &[]byte{0, 0},
+                                       [2]byte{0, 0},
                                        NewField(FieldData, []byte{
                                                0x00, 0x04, // field count
 
@@ -2124,17 +1922,13 @@ func TestHandleUpdateUser(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to create new accounts.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when action is modify user without required permission",
@@ -2143,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 {
@@ -2156,7 +1952,7 @@ func TestHandleUpdateUser(t *testing.T) {
                                },
                                t: NewTransaction(
                                        TranUpdateUser,
-                                       &[]byte{0, 0},
+                                       [2]byte{0, 0},
                                        NewField(FieldData, []byte{
                                                0x00, 0x04, // field count
 
@@ -2180,38 +1976,27 @@ func TestHandleUpdateUser(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to modify accounts.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when action is delete user without required permission",
                        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(
                                        TranUpdateUser,
-                                       &[]byte{0, 0},
+                                       [2]byte{0, 0},
                                        NewField(FieldData, []byte{
                                                0x00, 0x01,
                                                0x00, 0x65,
@@ -2222,26 +2007,18 @@ func TestHandleUpdateUser(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to delete accounts.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleUpdateUser(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleUpdateUser(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
-
+                       gotRes := HandleUpdateUser(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -2250,13 +2027,12 @@ func TestHandleUpdateUser(t *testing.T) {
 func TestHandleDelNewsArt(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "without required permission",
@@ -2271,30 +2047,23 @@ func TestHandleDelNewsArt(t *testing.T) {
                                },
                                t: NewTransaction(
                                        TranDelNewsArt,
-                                       &[]byte{0, 0},
+                                       [2]byte{0, 0},
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to delete news articles.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleDelNewsArt(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleDelNewsArt(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+                       gotRes := HandleDelNewsArt(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -2303,13 +2072,12 @@ func TestHandleDelNewsArt(t *testing.T) {
 func TestHandleDisconnectUser(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "without required permission",
@@ -2324,76 +2092,68 @@ func TestHandleDisconnectUser(t *testing.T) {
                                },
                                t: NewTransaction(
                                        TranDelNewsArt,
-                                       &[]byte{0, 0},
+                                       [2]byte{0, 0},
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to disconnect users.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when target user has 'cannot be disconnected' priv",
                        args: args{
                                cc: &ClientConn{
                                        Server: &Server{
-                                               Clients: map[uint16]*ClientConn{
-                                                       uint16(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
                                                }(),
                                        },
                                },
                                t: NewTransaction(
                                        TranDelNewsArt,
-                                       &[]byte{0, 0},
+                                       [2]byte{0, 0},
                                        NewField(FieldUserID, []byte{0, 1}),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("unnamed is not allowed to be disconnected.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleDisconnectUser(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleDisconnectUser(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+                       gotRes := HandleDisconnectUser(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -2402,13 +2162,12 @@ func TestHandleDisconnectUser(t *testing.T) {
 func TestHandleSendInstantMsg(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "without required permission",
@@ -2423,22 +2182,18 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                },
                                t: NewTransaction(
                                        TranDelNewsArt,
-                                       &[]byte{0, 0},
+                                       [2]byte{0, 0},
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to send private messages.")),
                                        },
                                },
                        },
-                       wantErr: assert.Error,
                },
                {
                        name: "when client 1 sends a message to client 2",
@@ -2447,48 +2202,46 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendPrivMsg)
+                                                       bits.Set(AccessSendPrivMsg)
                                                        return bits
                                                }(),
                                        },
-                                       ID:       &[]byte{0, 1},
+                                       ID:       [2]byte{0, 1},
                                        UserName: []byte("User1"),
                                        Server: &Server{
-                                               Clients: map[uint16]*ClientConn{
-                                                       uint16(2): {
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("Get", ClientID{0x0, 0x2}).Return(&ClientConn{
                                                                AutoReply: []byte(nil),
-                                                               Flags:     []byte{0, 0},
+                                                               Flags:     [2]byte{0, 0},
                                                        },
-                                               },
+                                                       )
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
                                        TranSendInstantMsg,
-                                       &[]byte{0, 1},
+                                       [2]byte{0, 1},
                                        NewField(FieldData, []byte("hai")),
                                        NewField(FieldUserID, []byte{0, 2}),
                                ),
                        },
                        wantRes: []Transaction{
-                               *NewTransaction(
+                               NewTransaction(
                                        TranServerMsg,
-                                       &[]byte{0, 2},
+                                       [2]byte{0, 2},
                                        NewField(FieldData, []byte("hai")),
                                        NewField(FieldUserName, []byte("User1")),
                                        NewField(FieldUserID, []byte{0, 1}),
                                        NewField(FieldOptions, []byte{0, 1}),
                                ),
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
-                                       Fields:    []Field(nil),
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
+                                       Fields:   []Field(nil),
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when client 2 has autoreply enabled",
@@ -2497,58 +2250,55 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendPrivMsg)
+                                                       bits.Set(AccessSendPrivMsg)
                                                        return bits
                                                }(),
                                        },
-                                       ID:       &[]byte{0, 1},
+                                       ID:       [2]byte{0, 1},
                                        UserName: []byte("User1"),
                                        Server: &Server{
-                                               Clients: map[uint16]*ClientConn{
-                                                       uint16(2): {
-                                                               Flags:     []byte{0, 0},
-                                                               ID:        &[]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(
                                        TranSendInstantMsg,
-                                       &[]byte{0, 1},
+                                       [2]byte{0, 1},
                                        NewField(FieldData, []byte("hai")),
                                        NewField(FieldUserID, []byte{0, 2}),
                                ),
                        },
                        wantRes: []Transaction{
-                               *NewTransaction(
+                               NewTransaction(
                                        TranServerMsg,
-                                       &[]byte{0, 2},
+                                       [2]byte{0, 2},
                                        NewField(FieldData, []byte("hai")),
                                        NewField(FieldUserName, []byte("User1")),
                                        NewField(FieldUserID, []byte{0, 1}),
                                        NewField(FieldOptions, []byte{0, 1}),
                                ),
-                               *NewTransaction(
+                               NewTransaction(
                                        TranServerMsg,
-                                       &[]byte{0, 1},
+                                       [2]byte{0, 1},
                                        NewField(FieldData, []byte("autohai")),
                                        NewField(FieldUserName, []byte("User2")),
                                        NewField(FieldUserID, []byte{0, 2}),
                                        NewField(FieldOptions, []byte{0, 1}),
                                ),
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
-                                       Fields:    []Field(nil),
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
+                                       Fields:   []Field(nil),
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when client 2 has refuse private messages enabled",
@@ -2557,58 +2307,52 @@ func TestHandleSendInstantMsg(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessSendPrivMsg)
+                                                       bits.Set(AccessSendPrivMsg)
                                                        return bits
                                                }(),
                                        },
-                                       ID:       &[]byte{0, 1},
+                                       ID:       [2]byte{0, 1},
                                        UserName: []byte("User1"),
                                        Server: &Server{
-                                               Clients: map[uint16]*ClientConn{
-                                                       uint16(2): {
-                                                               Flags:    []byte{255, 255},
-                                                               ID:       &[]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(
                                        TranSendInstantMsg,
-                                       &[]byte{0, 1},
+                                       [2]byte{0, 1},
                                        NewField(FieldData, []byte("hai")),
                                        NewField(FieldUserID, []byte{0, 2}),
                                ),
                        },
                        wantRes: []Transaction{
-                               *NewTransaction(
+                               NewTransaction(
                                        TranServerMsg,
-                                       &[]byte{0, 1},
+                                       [2]byte{0, 1},
                                        NewField(FieldData, []byte("User2 does not accept private messages.")),
                                        NewField(FieldUserName, []byte("User2")),
                                        NewField(FieldUserID, []byte{0, 2}),
                                        NewField(FieldOptions, []byte{0, 2}),
                                ),
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
-                                       Fields:    []Field(nil),
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
+                                       Fields:   []Field(nil),
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleSendInstantMsg(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleSendInstantMsg(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
-
+                       gotRes := HandleSendInstantMsg(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -2617,13 +2361,12 @@ func TestHandleSendInstantMsg(t *testing.T) {
 func TestHandleDeleteFile(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when user does not have required permission to delete a folder",
@@ -2636,7 +2379,7 @@ func TestHandleDeleteFile(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: func() string {
                                                                return "/fakeRoot/Files"
                                                        }(),
@@ -2656,11 +2399,11 @@ func TestHandleDeleteFile(t *testing.T) {
 
                                                        return mfs
                                                }(),
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
-                                       TranDeleteFile, &[]byte{0, 1},
+                                       TranDeleteFile, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testfile")),
                                        NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
@@ -2672,17 +2415,13 @@ func TestHandleDeleteFile(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to delete files.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "deletes all associated metadata files",
@@ -2691,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"
                                                        }(),
@@ -2721,11 +2460,11 @@ func TestHandleDeleteFile(t *testing.T) {
 
                                                        return mfs
                                                }(),
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
-                                       TranDeleteFile, &[]byte{0, 1},
+                                       TranDeleteFile, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testfile")),
                                        NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
@@ -2737,24 +2476,15 @@ func TestHandleDeleteFile(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x0, 0x0, 0x0, 0x0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
-                                       Fields:    []Field(nil),
+                                       IsReply: 0x01,
+                                       Fields:  []Field(nil),
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleDeleteFile(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleDeleteFile(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
-
+                       gotRes := HandleDeleteFile(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
 
                        tt.args.cc.Server.FS.(*MockFileStore).AssertExpectations(t)
@@ -2765,16 +2495,15 @@ func TestHandleDeleteFile(t *testing.T) {
 func TestHandleGetFileNameList(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
-                       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{
@@ -2785,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")
@@ -2794,7 +2523,7 @@ func TestHandleGetFileNameList(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranGetFileNameList, &[]byte{0, 1},
+                                       TranGetFileNameList, [2]byte{0, 1},
                                        NewField(FieldFilePath, []byte{
                                                0x00, 0x01,
                                                0x00, 0x00,
@@ -2805,24 +2534,20 @@ func TestHandleGetFileNameList(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to view drop boxes.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "with file root",
                        args: args{
                                cc: &ClientConn{
                                        Server: &Server{
-                                               Config: &Config{
+                                               Config: Config{
                                                        FileRoot: func() string {
                                                                path, _ := os.Getwd()
                                                                return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
@@ -2831,7 +2556,7 @@ func TestHandleGetFileNameList(t *testing.T) {
                                        },
                                },
                                t: NewTransaction(
-                                       TranGetFileNameList, &[]byte{0, 1},
+                                       TranGetFileNameList, [2]byte{0, 1},
                                        NewField(FieldFilePath, []byte{
                                                0x00, 0x00,
                                                0x00, 0x00,
@@ -2840,11 +2565,7 @@ func TestHandleGetFileNameList(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       IsReply: 0x01,
                                        Fields: []Field{
                                                NewField(
                                                        FieldFileNameWithInfo,
@@ -2858,7 +2579,7 @@ func TestHandleGetFileNameList(t *testing.T) {
                                                                                NameScript: [2]byte{},
                                                                                NameSize:   [2]byte{0, 0x0b},
                                                                        },
-                                                                       name: []byte("testfile-1k"),
+                                                                       Name: []byte("testfile-1k"),
                                                                }
                                                                b, _ := io.ReadAll(&fnwi)
                                                                return b
@@ -2867,16 +2588,11 @@ func TestHandleGetFileNameList(t *testing.T) {
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleGetFileNameList(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleGetFileNameList(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
-
+                       gotRes := HandleGetFileNameList(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -2885,13 +2601,12 @@ func TestHandleGetFileNameList(t *testing.T) {
 func TestHandleGetClientInfoText(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when user does not have required permission",
@@ -2904,27 +2619,23 @@ func TestHandleGetClientInfoText(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
-                                       TranGetClientInfoText, &[]byte{0, 1},
+                                       TranGetClientInfoText, [2]byte{0, 1},
                                        NewField(FieldUserID, []byte{0, 1}),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to get client info.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "with a valid user",
@@ -2935,49 +2646,42 @@ 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[uint16]*ClientConn{
-                                                       uint16(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, &[]byte{0, 1},
+                                       TranGetClientInfoText, [2]byte{0, 1},
                                        NewField(FieldUserID, []byte{0, 1}),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       IsReply: 0x01,
                                        Fields: []Field{
                                                NewField(FieldData, []byte(
                                                        strings.ReplaceAll(`Nickname:   Testy McTest
@@ -3011,15 +2715,11 @@ None.
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleGetClientInfoText(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleGetClientInfoText(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+                       gotRes := HandleGetClientInfoText(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -3028,13 +2728,12 @@ None.
 func TestHandleTranAgreed(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "normal request flow",
@@ -3043,23 +2742,34 @@ 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},
-                                       Flags:   []byte{0, 1},
+                                       Flags:   [2]byte{0, 1},
                                        Version: []byte{0, 1},
-                                       ID:      &[]byte{0, 1},
+                                       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(
-                                       TranAgreed, nil,
+                                       TranAgreed, [2]byte{},
                                        NewField(FieldUserName, []byte("username")),
                                        NewField(FieldUserIconID, []byte{0, 1}),
                                        NewField(FieldOptions, []byte{0, 0}),
@@ -3067,35 +2777,23 @@ func TestHandleTranAgreed(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x7a},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Type:     [2]byte{0, 0x7a},
                                        Fields: []Field{
                                                NewField(FieldBannerType, []byte("JPEG")),
                                        },
                                },
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
-                                       Fields:    []Field{},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
+                                       Fields:   []Field{},
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleTranAgreed(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleTranAgreed(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+                       gotRes := HandleTranAgreed(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -3104,16 +2802,15 @@ func TestHandleTranAgreed(t *testing.T) {
 func TestHandleSetClientUserInfo(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
-                       name: "when client does not have accessAnyName",
+                       name: "when client does not have AccessAnyName",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
@@ -3122,31 +2819,31 @@ func TestHandleSetClientUserInfo(t *testing.T) {
                                                        return bits
                                                }(),
                                        },
-                                       ID:       &[]byte{0, 1},
+                                       ID:       [2]byte{0, 1},
                                        UserName: []byte("Guest"),
-                                       Flags:    []byte{0, 1},
+                                       Flags:    [2]byte{0, 1},
                                        Server: &Server{
-                                               Clients: map[uint16]*ClientConn{
-                                                       uint16(1): {
-                                                               ID: &[]byte{0, 1},
-                                                       },
-                                               },
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("List").Return([]*ClientConn{
+                                                               {
+                                                                       ID: [2]byte{0, 1},
+                                                               },
+                                                       })
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
-                                       TranSetClientUserInfo, nil,
+                                       TranSetClientUserInfo, [2]byte{},
                                        NewField(FieldUserIconID, []byte{0, 1}),
                                        NewField(FieldUserName, []byte("NOPE")),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0x01, 0x2d},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Type:     [2]byte{0x01, 0x2d},
                                        Fields: []Field{
                                                NewField(FieldUserID, []byte{0, 1}),
                                                NewField(FieldUserIconID, []byte{0, 1}),
@@ -3154,16 +2851,11 @@ func TestHandleSetClientUserInfo(t *testing.T) {
                                                NewField(FieldUserName, []byte("Guest"))},
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleSetClientUserInfo(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleSetClientUserInfo(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
-
+                       gotRes := HandleSetClientUserInfo(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -3172,13 +2864,12 @@ func TestHandleSetClientUserInfo(t *testing.T) {
 func TestHandleDelNewsItem(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when user does not have permission to delete a news category",
@@ -3187,20 +2878,19 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        Account: &Account{
                                                Access: accessBitmap{},
                                        },
-                                       ID: &[]byte{0, 1},
+                                       ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
-                                                       "test": {
-                                                               Type:     [2]byte{0, 3},
-                                                               Count:    nil,
-                                                               NameSize: 0,
-                                                               Name:     "zz",
-                                                       },
-                                               }},
+                                               ThreadedNewsMgr: func() *mockThreadNewsMgr {
+                                                       m := mockThreadNewsMgr{}
+                                                       m.On("NewsItem", []string{"test"}).Return(NewsCategoryListData15{
+                                                               Type: NewsCategory,
+                                                       })
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
-                                       TranDelNewsItem, nil,
+                                       TranDelNewsItem, [2]byte{},
                                        NewField(FieldNewsPath,
                                                []byte{
                                                        0, 1,
@@ -3213,18 +2903,14 @@ func TestHandleDelNewsItem(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
+                                       clientID:  [2]byte{0, 1},
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to delete news categories.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when user does not have permission to delete a news folder",
@@ -3233,20 +2919,19 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        Account: &Account{
                                                Access: accessBitmap{},
                                        },
-                                       ID: &[]byte{0, 1},
+                                       ID: [2]byte{0, 1},
                                        Server: &Server{
-                                               ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
-                                                       "testcat": {
-                                                               Type:     [2]byte{0, 2},
-                                                               Count:    nil,
-                                                               NameSize: 0,
-                                                               Name:     "test",
-                                                       },
-                                               }},
+                                               ThreadedNewsMgr: func() *mockThreadNewsMgr {
+                                                       m := mockThreadNewsMgr{}
+                                                       m.On("NewsItem", []string{"test"}).Return(NewsCategoryListData15{
+                                                               Type: NewsBundle,
+                                                       })
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
-                                       TranDelNewsItem, nil,
+                                       TranDelNewsItem, [2]byte{},
                                        NewField(FieldNewsPath,
                                                []byte{
                                                        0, 1,
@@ -3259,18 +2944,14 @@ func TestHandleDelNewsItem(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
+                                       clientID:  [2]byte{0, 1},
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to delete news folders.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when user deletes a news folder",
@@ -3279,30 +2960,22 @@ func TestHandleDelNewsItem(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessNewsDeleteFldr)
+                                                       bits.Set(AccessNewsDeleteFldr)
                                                        return bits
                                                }(),
                                        },
-                                       ID: &[]byte{0, 1},
+                                       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},
-                                                               Count:    nil,
-                                                               NameSize: 0,
-                                                               Name:     "test",
-                                                       },
-                                               }},
                                        },
                                },
                                t: NewTransaction(
-                                       TranDelNewsItem, nil,
+                                       TranDelNewsItem, [2]byte{},
                                        NewField(FieldNewsPath,
                                                []byte{
                                                        0, 1,
@@ -3315,24 +2988,17 @@ func TestHandleDelNewsItem(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
-                                       Fields:    []Field{},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
+                                       Fields:   []Field{},
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleDelNewsItem(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleDelNewsItem(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+                       gotRes := HandleDelNewsItem(tt.args.cc, &tt.args.t)
+
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -3341,43 +3007,35 @@ func TestHandleDelNewsItem(t *testing.T) {
 func TestHandleTranOldPostNews(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when user does not have required permission",
                        args: args{
                                cc: &ClientConn{
                                        Account: &Account{
-                                               Access: func() accessBitmap {
-                                                       var bits accessBitmap
-                                                       return bits
-                                               }(),
+                                               Access: accessBitmap{},
                                        },
                                },
                                t: NewTransaction(
-                                       TranOldPostNews, &[]byte{0, 1},
+                                       TranOldPostNews, [2]byte{0, 1},
                                        NewField(FieldData, []byte("hai")),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to post news.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when user posts news update",
@@ -3386,43 +3044,46 @@ 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(
-                                       TranOldPostNews, &[]byte{0, 1},
+                                       TranOldPostNews, [2]byte{0, 1},
                                        NewField(FieldData, []byte("hai")),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       IsReply: 0x01,
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleTranOldPostNews(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleTranOldPostNews(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+                       gotRes := HandleTranOldPostNews(tt.args.cc, &tt.args.t)
 
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
@@ -3432,13 +3093,12 @@ func TestHandleTranOldPostNews(t *testing.T) {
 func TestHandleInviteNewChat(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when user does not have required permission",
@@ -3451,75 +3111,67 @@ func TestHandleInviteNewChat(t *testing.T) {
                                                }(),
                                        },
                                },
-                               t: NewTransaction(TranInviteNewChat, &[]byte{0, 1}),
+                               t: NewTransaction(TranInviteNewChat, [2]byte{0, 1}),
                        },
                        wantRes: []Transaction{
                                {
-                                       Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to request private chat.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when userA invites userB to new private chat",
                        args: args{
                                cc: &ClientConn{
-                                       ID: &[]byte{0, 1},
+                                       ID: [2]byte{0, 1},
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessOpenChat)
+                                                       bits.Set(AccessOpenChat)
                                                        return bits
                                                }(),
                                        },
                                        UserName: []byte("UserA"),
                                        Icon:     []byte{0, 1},
-                                       Flags:    []byte{0, 0},
+                                       Flags:    [2]byte{0, 0},
                                        Server: &Server{
-                                               Clients: map[uint16]*ClientConn{
-                                                       uint16(2): {
-                                                               ID:       &[]byte{0, 2},
+                                               ClientMgr: func() *MockClientMgr {
+                                                       m := MockClientMgr{}
+                                                       m.On("Get", ClientID{0x0, 0x2}).Return(&ClientConn{
+                                                               ID:       [2]byte{0, 2},
                                                                UserName: []byte("UserB"),
-                                                               Flags:    []byte{0, 0},
-                                                       },
-                                               },
-                                               PrivateChats: make(map[uint32]*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(
-                                       TranInviteNewChat, &[]byte{0, 1},
+                                       TranInviteNewChat, [2]byte{0, 1},
                                        NewField(FieldUserID, []byte{0, 2}),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 2},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x71},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 2},
+                                       Type:     [2]byte{0, 0x71},
                                        Fields: []Field{
                                                NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
                                                NewField(FieldUserName, []byte("UserA")),
                                                NewField(FieldUserID, []byte{0, 1}),
                                        },
                                },
-
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
                                        Fields: []Field{
                                                NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
                                                NewField(FieldUserName, []byte("UserA")),
@@ -3529,47 +3181,49 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "when userA invites userB to new private chat, but UserB has refuse private chat enabled",
                        args: args{
                                cc: &ClientConn{
-                                       ID: &[]byte{0, 1},
+                                       ID: [2]byte{0, 1},
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessOpenChat)
+                                                       bits.Set(AccessOpenChat)
                                                        return bits
                                                }(),
                                        },
                                        UserName: []byte("UserA"),
                                        Icon:     []byte{0, 1},
-                                       Flags:    []byte{0, 0},
+                                       Flags:    [2]byte{0, 0},
                                        Server: &Server{
-                                               Clients: map[uint16]*ClientConn{
-                                                       uint16(2): {
-                                                               ID:       &[]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:    []byte{255, 255},
-                                                       },
-                                               },
-                                               PrivateChats: make(map[uint32]*PrivateChat),
+                                                               Flags:    [2]byte{255, 255},
+                                                       })
+                                                       return &m
+                                               }(),
+                                               ChatMgr: func() *MockChatManager {
+                                                       m := MockChatManager{}
+                                                       m.On("New", mock.AnythingOfType("*hotline.ClientConn")).Return(ChatID{0x52, 0xfd, 0xfc, 0x07})
+                                                       return &m
+                                               }(),
                                        },
                                },
                                t: NewTransaction(
-                                       TranInviteNewChat, &[]byte{0, 1},
+                                       TranInviteNewChat, [2]byte{0, 1},
                                        NewField(FieldUserID, []byte{0, 2}),
                                ),
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x00,
-                                       Type:      []byte{0, 0x68},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       Type:     [2]byte{0, 0x68},
                                        Fields: []Field{
                                                NewField(FieldData, []byte("UserB does not accept private chats.")),
                                                NewField(FieldUserName, []byte("UserB")),
@@ -3578,12 +3232,8 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        },
                                },
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
                                        Fields: []Field{
                                                NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
                                                NewField(FieldUserName, []byte("UserA")),
@@ -3593,16 +3243,13 @@ func TestHandleInviteNewChat(t *testing.T) {
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       rand.Seed(1)
-                       gotRes, err := HandleInviteNewChat(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleInviteNewChat(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+
+                       gotRes := HandleInviteNewChat(tt.args.cc, &tt.args.t)
+
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -3611,53 +3258,90 @@ func TestHandleInviteNewChat(t *testing.T) {
 func TestHandleGetNewsArtData(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        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, &[]byte{0, 1},
+                                       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{
                                {
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0x9a, 0xcb, 0x04, 0x42},
-                                       ErrorCode: []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")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleGetNewsArtData(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleGetNewsArtData(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+                       gotRes := HandleGetNewsArtData(tt.args.cc, &tt.args.t)
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -3666,13 +3350,12 @@ func TestHandleGetNewsArtData(t *testing.T) {
 func TestHandleGetNewsArtNameList(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when user does not have required permission",
@@ -3685,33 +3368,78 @@ func TestHandleGetNewsArtNameList(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
-                                       TranGetNewsArtNameList, &[]byte{0, 1},
+                                       TranGetNewsArtNameList, [2]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                {
                                        Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       Type:      [2]byte{0, 0},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to read news.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
+               //{
+               //      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) {
-                       gotRes, err := HandleGetNewsArtNameList(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleGetNewsArtNameList(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+                       gotRes := HandleGetNewsArtNameList(tt.args.cc, &tt.args.t)
+
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
@@ -3720,13 +3448,12 @@ func TestHandleGetNewsArtNameList(t *testing.T) {
 func TestHandleNewNewsFldr(t *testing.T) {
        type args struct {
                cc *ClientConn
-               t  *Transaction
+               t  Transaction
        }
        tests := []struct {
                name    string
                args    args
                wantRes []Transaction
-               wantErr assert.ErrorAssertionFunc
        }{
                {
                        name: "when user does not have required permission",
@@ -3739,25 +3466,24 @@ func TestHandleNewNewsFldr(t *testing.T) {
                                                }(),
                                        },
                                        Server: &Server{
-                                               Accounts: map[string]*Account{},
+                                               //Accounts: map[string]*Account{},
                                        },
                                },
                                t: NewTransaction(
-                                       TranGetNewsArtNameList, &[]byte{0, 1},
+                                       TranGetNewsArtNameList, [2]byte{0, 1},
                                ),
                        },
                        wantRes: []Transaction{
                                {
                                        Flags:     0x00,
                                        IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 1},
+                                       Type:      [2]byte{0, 0},
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
                                        Fields: []Field{
                                                NewField(FieldError, []byte("You are not allowed to create news folders.")),
                                        },
                                },
                        },
-                       wantErr: assert.NoError,
                },
                {
                        name: "with a valid request",
@@ -3766,32 +3492,22 @@ func TestHandleNewNewsFldr(t *testing.T) {
                                        Account: &Account{
                                                Access: func() accessBitmap {
                                                        var bits accessBitmap
-                                                       bits.Set(accessNewsCreateFldr)
+                                                       bits.Set(AccessNewsCreateFldr)
                                                        return bits
                                                }(),
                                        },
                                        logger: NewTestLogger(),
-                                       ID:     &[]byte{0, 1},
+                                       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},
-                                                               Count:    nil,
-                                                               NameSize: 0,
-                                                               Name:     "test",
-                                                               SubCats:  make(map[string]NewsCategoryListData15),
-                                                       },
-                                               }},
                                        },
                                },
                                t: NewTransaction(
-                                       TranGetNewsArtNameList, &[]byte{0, 1},
+                                       TranGetNewsArtNameList, [2]byte{0, 1},
                                        NewField(FieldFileName, []byte("testFolder")),
                                        NewField(FieldNewsPath,
                                                []byte{
@@ -3805,30 +3521,25 @@ func TestHandleNewNewsFldr(t *testing.T) {
                        },
                        wantRes: []Transaction{
                                {
-                                       clientID:  &[]byte{0, 1},
-                                       Flags:     0x00,
-                                       IsReply:   0x01,
-                                       Type:      []byte{0, 0},
-                                       ID:        []byte{0, 0, 0, 0},
-                                       ErrorCode: []byte{0, 0, 0, 0},
-                                       Fields:    []Field{},
+                                       clientID: [2]byte{0, 1},
+                                       IsReply:  0x01,
+                                       Fields:   []Field{},
                                },
                        },
-                       wantErr: assert.NoError,
                },
                //{
-               //      name: "when there is an error writing the threaded news file",
+               //      Name: "when there is an error writing the threaded news file",
                //      args: args{
                //              cc: &ClientConn{
                //                      Account: &Account{
                //                              Access: func() accessBitmap {
                //                                      var bits accessBitmap
-               //                                      bits.Set(accessNewsCreateFldr)
+               //                                      bits.Set(AccessNewsCreateFldr)
                //                                      return bits
                //                              }(),
                //                      },
                //                      logger: NewTestLogger(),
-               //                      ID:     &[]byte{0, 1},
+               //                      Type:     [2]byte{0, 1},
                //                      Server: &Server{
                //                              ConfigDir: "/fakeConfigRoot",
                //                              FS: func() *MockFileStore {
@@ -3848,7 +3559,7 @@ func TestHandleNewNewsFldr(t *testing.T) {
                //                      },
                //              },
                //              t: NewTransaction(
-               //                      TranGetNewsArtNameList, &[]byte{0, 1},
+               //                      TranGetNewsArtNameList, [2]byte{0, 1},
                //                      NewField(FieldFileName, []byte("testFolder")),
                //                      NewField(FieldNewsPath,
                //                              []byte{
@@ -3862,26 +3573,121 @@ func TestHandleNewNewsFldr(t *testing.T) {
                //      },
                //      wantRes: []Transaction{
                //              {
-               //                      clientID:  &[]byte{0, 1},
+               //                      clientID:  [2]byte{0, 1},
                //                      Flags:     0x00,
                //                      IsReply:   0x01,
-               //                      Type:      []byte{0, 0},
-               //                      ErrorCode: []byte{0, 0, 0, 1},
+               //                      Type:      [2]byte{0, 0},
+               //                      ErrorCode: [4]byte{0, 0, 0, 1},
                //                      Fields: []Field{
                //                              NewField(FieldError, []byte("Error creating news folder.")),
                //                      },
                //              },
                //      },
-               //      wantErr: assert.Error,
-               // },
        }
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
-                       gotRes, err := HandleNewNewsFldr(tt.args.cc, tt.args.t)
-                       if !tt.wantErr(t, err, fmt.Sprintf("HandleNewNewsFldr(%v, %v)", tt.args.cc, tt.args.t)) {
-                               return
-                       }
+                       gotRes := HandleNewNewsFldr(tt.args.cc, &tt.args.t)
+
                        tranAssertEqual(t, tt.wantRes, gotRes)
                })
        }
 }
+
+func TestHandleDownloadBanner(t *testing.T) {
+       type args struct {
+               cc *ClientConn
+               t  Transaction
+       }
+       tests := []struct {
+               name    string
+               args    args
+               wantRes []Transaction
+       }{
+               // TODO: Add test cases.
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       gotRes := HandleDownloadBanner(tt.args.cc, &tt.args.t)
+
+                       assert.Equalf(t, tt.wantRes, gotRes, "HandleDownloadBanner(%v, %v)", tt.args.cc, &tt.args.t)
+               })
+       }
+}
+
+func TestHandlePostNewsArt(t *testing.T) {
+       type args struct {
+               cc *ClientConn
+               t  Transaction
+       }
+       tests := []struct {
+               name    string
+               args    args
+               wantRes []Transaction
+       }{
+               {
+                       name: "without required permission",
+                       args: args{
+                               cc: &ClientConn{
+                                       Account: &Account{
+                                               Access: func() accessBitmap {
+                                                       var bits accessBitmap
+                                                       return bits
+                                               }(),
+                                       },
+                               },
+                               t: NewTransaction(
+                                       TranPostNewsArt,
+                                       [2]byte{0, 0},
+                               ),
+                       },
+                       wantRes: []Transaction{
+                               {
+                                       IsReply:   0x01,
+                                       ErrorCode: [4]byte{0, 0, 0, 1},
+                                       Fields: []Field{
+                                               NewField(FieldError, []byte("You are not allowed to post news articles.")),
+                                       },
+                               },
+                       },
+               },
+               {
+                       name: "with required permission",
+                       args: args{
+                               cc: &ClientConn{
+                                       Server: &Server{
+                                               ThreadedNewsMgr: func() *mockThreadNewsMgr {
+                                                       m := mockThreadNewsMgr{}
+                                                       m.On("PostArticle", []string{"www"}, uint32(0), mock.AnythingOfType("hotline.NewsArtData")).Return(nil)
+                                                       return &m
+                                               }(),
+                                       },
+                                       Account: &Account{
+                                               Access: func() accessBitmap {
+                                                       var bits accessBitmap
+                                                       bits.Set(AccessNewsPostArt)
+                                                       return bits
+                                               }(),
+                                       },
+                               },
+                               t: NewTransaction(
+                                       TranPostNewsArt,
+                                       [2]byte{0, 0},
+                                       NewField(FieldNewsPath, []byte{0x00, 0x01, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77}),
+                                       NewField(FieldNewsArtID, []byte{0x00, 0x00, 0x00, 0x00}),
+                               ),
+                       },
+                       wantRes: []Transaction{
+                               {
+                                       IsReply:   0x01,
+                                       ErrorCode: [4]byte{0, 0, 0, 0},
+                                       Fields:    []Field{},
+                               },
+                       },
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       tranAssertEqual(t, tt.wantRes, HandlePostNewsArt(tt.args.cc, &tt.args.t))
+               })
+       }
+}