]> git.r.bdr.sh - rbdr/mobius/blobdiff - hotline/server_test.go
Convert bespoke methods to io.Reader/io.Writer interfaces
[rbdr/mobius] / hotline / server_test.go
index c69177f91d4ef4ceeccdf16c8befa6ddf8652a48..7e2608ed603f46f098feaf233d418ba2a0d17880 100644 (file)
 package hotline
 
-//
-//import (
-//     "bytes"
-//     "fmt"
-//     "github.com/google/go-cmp/cmp"
-//     "io/ioutil"
-//     "math/big"
-//     "net"
-//     "strings"
-//     "sync"
-//     "testing"
-//)
-//
-//type transactionTest struct {
-//     description string      // Human understandable description
-//     account     Account     // Account struct for a user that will test transaction will execute under
-//     request     Transaction // transaction that will be sent by the client to the server
-//     want        Transaction // transaction that the client expects to receive in response
-//     setup       func()      // Optional setup required for the test scenario
-//     teardown    func()      // Optional teardown for test scenario
-//}
-//
-//func (tt *transactionTest) Setup(srv *Server) error {
-//     if err := srv.NewUser(tt.account.Login, tt.account.Name, NegatedUserString([]byte(tt.account.Password)), tt.account.Access); err != nil {
-//             return err
-//     }
-//
-//     if tt.setup != nil {
-//             tt.setup()
-//     }
-//
-//     return nil
-//}
-//
-//func (tt *transactionTest) Teardown(srv *Server) error {
-//     if err := srv.DeleteUser(tt.account.Login); err != nil {
-//             return err
-//     }
-//
-//     if tt.teardown != nil {
-//             tt.teardown()
-//     }
-//
-//     return nil
-//}
-//
-//// StartTestServer
-//func StartTestServer() (srv *Server, lnPort int) {
-//     hotlineServer, _ := NewServer("test/config/")
-//     ln, err := net.Listen("tcp", ":0")
-//
-//     if err != nil {
-//             panic(err)
-//     }
-//     go func() {
-//             for {
-//                     conn, _ := ln.Accept()
-//                     go hotlineServer.HandleConnection(conn)
-//             }
-//     }()
-//     return hotlineServer, ln.Addr().(*net.TCPAddr).Port
-//}
-//
-//func StartTestClient(serverPort int, login, passwd string) (*Client, error) {
-//     c := NewClient("")
-//
-//     err := c.JoinServer(fmt.Sprintf(":%v", serverPort), login, passwd)
-//     if err != nil {
-//             return nil, err
-//     }
-//
-//     return c, nil
-//}
-//
-//func StartTestServerWithClients(clientCount int) ([]*Client, int) {
-//     _, serverPort := StartTestServer()
-//
-//     var clients []*Client
-//     for i := 0; i < clientCount; i++ {
-//             client, err := StartTestClient(serverPort, "admin", "")
-//             if err != nil {
-//                     panic(err)
-//             }
-//             clients = append(clients, client)
-//     }
-//     clients[0].ReadN(2)
-//
-//     return clients, serverPort
-//}
-//
+import (
+       "bytes"
+       "context"
+       "fmt"
+       "github.com/stretchr/testify/assert"
+       "go.uber.org/zap"
+       "io"
+       "os"
+       "sync"
+       "testing"
+)
 
-////func TestHandleTranAgreed(t *testing.T) {
-////   clients, _ := StartTestServerWithClients(2)
-////
-////   chatMsg := "Test Chat"
-////
-////   // Assert that both clients should receive the user join notification
-////   var wg sync.WaitGroup
-////   for _, client := range clients {
-////           wg.Add(1)
-////           go func(wg *sync.WaitGroup, c *Client) {
-////                   defer wg.Done()
-////
-////                   receivedMsg := c.ReadTransactions()[0].GetField(fieldData).Data
-////
-////                   want := []byte(fmt.Sprintf("test: %s\r", chatMsg))
-////                   if bytes.Compare(receivedMsg, want) != 0 {
-////                           t.Errorf("%q, want %q", receivedMsg, want)
-////                   }
-////           }(&wg, client)
-////   }
-////
-////   trans := clients[1].ReadTransactions()
-////   spew.Dump(trans)
-////
-////   // Send the agreement
-////   clients[1].Connection.Write(
-////           NewTransaction(
-////                   tranAgreed, 0,
-////                   []Field{
-////                           NewField(fieldUserName, []byte("testUser")),
-////                           NewField(fieldUserIconID, []byte{0x00,0x07}),
-////                   },
-////           ).Payload(),
-////   )
-////
-////   wg.Wait()
-////}
-//
-//func TestChatSend(t *testing.T) {
-//     //srvPort := StartTestServer()
-//     //
-//     //senderClient := NewClient("senderClient")
-//     //senderClient.JoinServer(fmt.Sprintf(":%v", srvPort), "", "")
-//     //
-//     //receiverClient := NewClient("receiverClient")
-//     //receiverClient.JoinServer(fmt.Sprintf(":%v", srvPort), "", "")
-//
-//     clients, _ := StartTestServerWithClients(2)
-//
-//     chatMsg := "Test Chat"
-//
-//     // Both clients should receive the chatMsg
-//     var wg sync.WaitGroup
-//     for _, client := range clients {
-//             wg.Add(1)
-//             go func(wg *sync.WaitGroup, c *Client) {
-//                     defer wg.Done()
-//
-//                     receivedMsg := c.ReadTransactions()[0].GetField(fieldData).Data
-//
-//                     want := []byte(fmt.Sprintf("         test:  %s\r", chatMsg))
-//                     if bytes.Compare(receivedMsg, want) != 0 {
-//                             t.Errorf("%q, want %q", receivedMsg, want)
-//                     }
-//             }(&wg, client)
-//     }
-//
-//     // Send the chatMsg
-//     clients[1].Send(
-//             NewTransaction(
-//                     tranChatSend, 0,
-//                     []Field{
-//                             NewField(fieldData, []byte(chatMsg)),
-//                     },
-//             ),
-//     )
-//
-//     wg.Wait()
-//}
-//
-//func TestSetClientUserInfo(t *testing.T) {
-//     clients, _ := StartTestServerWithClients(2)
-//
-//     newIcon := []byte{0x00, 0x01}
-//     newUserName := "newName"
-//
-//     // Both clients should receive the chatMsg
-//     var wg sync.WaitGroup
-//     for _, client := range clients {
-//             wg.Add(1)
-//             go func(wg *sync.WaitGroup, c *Client) {
-//                     defer wg.Done()
-//
-//                     tran := c.ReadTransactions()[0]
-//
-//                     want := []byte(newUserName)
-//                     got := tran.GetField(fieldUserName).Data
-//                     if bytes.Compare(got, want) != 0 {
-//                             t.Errorf("%q, want %q", got, want)
-//                     }
-//             }(&wg, client)
-//     }
-//
-//     _, err := clients[1].Connection.Write(
-//             NewTransaction(
-//                     tranSetClientUserInfo, 0,
-//                     []Field{
-//                             NewField(fieldUserIconID, newIcon),
-//                             NewField(fieldUserName, []byte(newUserName)),
-//                     },
-//             ).Payload(),
-//     )
-//     if err != nil {
-//             t.Errorf("%v", err)
-//     }
-//
-//     wg.Wait()
-//}
-//
-//// TestSendInstantMsg tests that client A can send an instant message to client B
-////
-//func TestSendInstantMsg(t *testing.T) {
-//     clients, _ := StartTestServerWithClients(2)
-//
-//     instantMsg := "Test IM"
-//
-//     var wg sync.WaitGroup
-//     wg.Add(1)
-//     go func(wg *sync.WaitGroup, c *Client) {
-//             defer wg.Done()
-//
-//             tran := c.WaitForTransaction(tranServerMsg)
-//
-//             receivedMsg := tran.GetField(fieldData).Data
-//             want := []byte(fmt.Sprintf("%s", instantMsg))
-//             if bytes.Compare(receivedMsg, want) != 0 {
-//                     t.Errorf("%q, want %q", receivedMsg, want)
-//             }
-//     }(&wg, clients[0])
-//
-//     _ = clients[1].Send(
-//             NewTransaction(tranGetUserNameList, 0, []Field{}),
-//     )
-//     //connectedUsersTran := clients[1].ReadTransactions()[0]
-//     ////connectedUsers := connectedUsersTran.Fields[0].Data[0:2]
-//     //spew.Dump(connectedUsersTran.Fields)
-//     //firstUserID := connectedUsersTran.Fields[0].Data[0:2]
-//     //
-//     //spew.Dump(firstUserID)
-//
-//     // Send the IM
-//     err := clients[1].Send(
-//             NewTransaction(
-//                     tranSendInstantMsg, 0,
-//                     []Field{
-//                             NewField(fieldData, []byte(instantMsg)),
-//                             NewField(fieldUserName, clients[1].UserName),
-//                             NewField(fieldUserID, []byte{0, 2}),
-//                             NewField(fieldOptions, []byte{0, 1}),
-//                     },
-//             ),
-//     )
-//     if err != nil {
-//             t.Error(err)
-//     }
-//
-//     wg.Wait()
-//}
-//
-//func TestOldPostNews(t *testing.T) {
-//     clients, _ := StartTestServerWithClients(2)
-//
-//     newsPost := "Test News Post"
-//
-//     var wg sync.WaitGroup
-//     wg.Add(1)
-//     go func(wg *sync.WaitGroup, c *Client) {
-//             defer wg.Done()
-//
-//             receivedMsg := c.ReadTransactions()[0].GetField(fieldData).Data
-//
-//             if strings.Contains(string(receivedMsg), newsPost) == false {
-//                     t.Errorf("news post missing")
-//             }
-//     }(&wg, clients[0])
-//
-//     clients[1].Connection.Write(
-//             NewTransaction(
-//                     tranOldPostNews, 0,
-//                     []Field{
-//                             NewField(fieldData, []byte(newsPost)),
-//                     },
-//             ).Payload(),
-//     )
-//
-//     wg.Wait()
-//}
-//
-//// TODO: Fixme
-////func TestGetFileNameList(t *testing.T) {
-////   clients, _ := StartTestServerWithClients(2)
-////
-////   clients[0].Connection.Write(
-////           NewTransaction(
-////                   tranGetFileNameList, 0,
-////                   []Field{},
-////           ).Payload(),
-////   )
-////
-////   ts := clients[0].ReadTransactions()
-////   testfileSit := ReadFileNameWithInfo(ts[0].Fields[1].Data)
-////
-////   want := "testfile.sit"
-////   got := testfileSit.Name
-////   diff := cmp.Diff(want, got)
-////   if diff != "" {
-////           t.Fatalf(diff)
-////   }
-////   if testfileSit.Name != "testfile.sit" {
-////           t.Errorf("news post missing")
-////           t.Errorf("%q, want %q", testfileSit.Name, "testfile.sit")
-////   }
-////}
-//
-//func TestNewsCategoryList(t *testing.T) {
-//     clients, _ := StartTestServerWithClients(2)
-//     client := clients[0]
-//
-//     client.Send(
-//             NewTransaction(
-//                     tranGetNewsCatNameList, 0,
-//                     []Field{},
-//             ),
-//     )
-//
-//     ts := client.ReadTransactions()
-//     cats := ts[0].GetFields(fieldNewsCatListData15)
-//
-//     newsCat := ReadNewsCategoryListData(cats[0].Data)
-//     want := "TestBundle"
-//     got := newsCat.Name
-//     diff := cmp.Diff(want, got)
-//     if diff != "" {
-//             t.Fatalf(diff)
-//     }
-//
-//     newsBundle := ReadNewsCategoryListData(cats[1].Data)
-//     want = "TestCat"
-//     got = newsBundle.Name
-//     diff = cmp.Diff(want, got)
-//     if diff != "" {
-//             t.Fatalf(diff)
-//     }
-//}
-//
-//func TestNestedNewsCategoryList(t *testing.T) {
-//     clients, _ := StartTestServerWithClients(2)
-//     client := clients[0]
-//     newsPath := NewsPath{
-//             []string{
-//                     "TestBundle",
-//                     "NestedBundle",
-//             },
-//     }
-//
-//     _, err := client.Connection.Write(
-//             NewTransaction(
-//                     tranGetNewsCatNameList, 0,
-//                     []Field{
-//                             NewField(
-//                                     fieldNewsPath,
-//                                     newsPath.Payload(),
-//                             ),
-//                     },
-//             ).Payload(),
-//     )
-//     if err != nil {
-//             t.Errorf("%v", err)
-//     }
-//
-//     ts := client.ReadTransactions()
-//     cats := ts[0].GetFields(fieldNewsCatListData15)
-//
-//     newsCat := ReadNewsCategoryListData(cats[0].Data)
-//     want := "NestedCat"
-//     got := newsCat.Name
-//     diff := cmp.Diff(want, got)
-//     if diff != "" {
-//             t.Fatalf(diff)
-//     }
-//}
-//
-//func TestFileDownload(t *testing.T) {
-//     clients, _ := StartTestServerWithClients(2)
-//     client := clients[0]
-//
-//     type want struct {
-//             fileSize     []byte
-//             transferSize []byte
-//             waitingCount []byte
-//             refNum       []byte
-//     }
-//     var tests = []struct {
-//             fileName string
-//             want     want
-//     }{
-//             {
-//                     fileName: "testfile.sit",
-//                     want: want{
-//                             fileSize:     []byte{0x0, 0x0, 0x0, 0x13},
-//                             transferSize: []byte{0x0, 0x0, 0x0, 0xa1},
-//                     },
-//             },
-//             {
-//                     fileName: "testfile.txt",
-//                     want: want{
-//                             fileSize:     []byte{0x0, 0x0, 0x0, 0x17},
-//                             transferSize: []byte{0x0, 0x0, 0x0, 0xa5},
-//                     },
-//             },
-//     }
-//
-//     for _, test := range tests {
-//             _, err := client.Connection.Write(
-//                     NewTransaction(
-//                             tranDownloadFile, 0,
-//                             []Field{
-//                                     NewField(fieldFileName, []byte(test.fileName)),
-//                                     NewField(fieldFilePath, []byte("")),
-//                             },
-//                     ).Payload(),
-//             )
-//             if err != nil {
-//                     t.Errorf("%v", err)
-//             }
-//             tran := client.ReadTransactions()[0]
-//
-//             if got := tran.GetField(fieldFileSize).Data; bytes.Compare(got, test.want.fileSize) != 0 {
-//                     t.Errorf("TestFileDownload: fileSize got %#v, want %#v", got, test.want.fileSize)
-//             }
-//
-//             if got := tran.GetField(fieldTransferSize).Data; bytes.Compare(got, test.want.transferSize) != 0 {
-//                     t.Errorf("TestFileDownload: fieldTransferSize: %s: got %#v, want %#v", test.fileName, got, test.want.transferSize)
-//             }
-//     }
-//}
-//
-//func TestFileUpload(t *testing.T) {
-//     clients, _ := StartTestServerWithClients(2)
-//     client := clients[0]
-//
-//     var tests = []struct {
-//             fileName string
-//             want     Transaction
-//     }{
-//             {
-//                     fileName: "testfile.sit",
-//                     want: Transaction{
-//                             Fields: []Field{
-//                                     NewField(fieldRefNum, []byte{0x16, 0x3f, 0x5f, 0xf}),
-//                             },
-//                     },
-//             },
-//     }
-//
-//     for _, test := range tests {
-//             err := client.Send(
-//                     NewTransaction(
-//                             tranUploadFile, 0,
-//                             []Field{
-//                                     NewField(fieldFileName, []byte(test.fileName)),
-//                                     NewField(fieldFilePath, []byte("")),
-//                             },
-//                     ),
-//             )
-//             if err != nil {
-//                     t.Errorf("%v", err)
-//             }
-//             tran := client.ReadTransactions()[0]
-//
-//             for _, f := range test.want.Fields {
-//                     got := tran.GetField(f.Uint16ID()).Data
-//                     want := test.want.GetField(fieldRefNum).Data
-//                     if bytes.Compare(got, want) != 0 {
-//                             t.Errorf("xxx: yyy got %#v, want %#v", got, want)
-//                     }
-//             }
-//     }
-//}
-//
-//// TODO: Make canonical
-//func TestNewUser(t *testing.T) {
-//     srv, port := StartTestServer()
-//
-//     var tests = []struct {
-//             description string
-//             setup       func()
-//             teardown    func()
-//             account     Account
-//             request     Transaction
-//             want        Transaction
-//     }{
-//             {
-//                     description: "a valid new account",
-//                     teardown: func() {
-//                             _ = srv.DeleteUser("testUser")
-//                     },
-//                     account: Account{
-//                             Login:    "test",
-//                             Name:     "unnamed",
-//                             Password: "test",
-//                             Access:   []byte{255, 255, 255, 255, 255, 255, 255, 255},
-//                     },
-//                     request: NewTransaction(
-//                             tranNewUser, 0,
-//                             []Field{
-//                                     NewField(fieldUserLogin, []byte(NegatedUserString([]byte("testUser")))),
-//                                     NewField(fieldUserName, []byte("testUserName")),
-//                                     NewField(fieldUserPassword, []byte(NegatedUserString([]byte("testPw")))),
-//                                     NewField(fieldUserAccess, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
-//                             },
-//                     ),
-//                     want: Transaction{
-//                             Fields: []Field{},
-//                     },
-//             },
-//             {
-//                     description: "a newUser request from a user without the required access",
-//                     teardown: func() {
-//                             _ = srv.DeleteUser("testUser")
-//                     },
-//                     account: Account{
-//                             Login:    "test",
-//                             Name:     "unnamed",
-//                             Password: "test",
-//                             Access:   []byte{0, 0, 0, 0, 0, 0, 0, 0},
-//                     },
-//                     request: NewTransaction(
-//                             tranNewUser, 0,
-//                             []Field{
-//                                     NewField(fieldUserLogin, []byte(NegatedUserString([]byte("testUser")))),
-//                                     NewField(fieldUserName, []byte("testUserName")),
-//                                     NewField(fieldUserPassword, []byte(NegatedUserString([]byte("testPw")))),
-//                                     NewField(fieldUserAccess, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
-//                             },
-//                     ),
-//                     want: Transaction{
-//                             Fields: []Field{
-//                                     NewField(fieldError, []byte("You are not allowed to create new accounts.")),
-//                             },
-//                     },
-//             },
-//             {
-//                     description: "a request to create a user that already exists",
-//                     teardown: func() {
-//                             _ = srv.DeleteUser("testUser")
-//                     },
-//                     account: Account{
-//                             Login:    "test",
-//                             Name:     "unnamed",
-//                             Password: "test",
-//                             Access:   []byte{255, 255, 255, 255, 255, 255, 255, 255},
-//                     },
-//                     request: NewTransaction(
-//                             tranNewUser, 0,
-//                             []Field{
-//                                     NewField(fieldUserLogin, []byte(NegatedUserString([]byte("guest")))),
-//                                     NewField(fieldUserName, []byte("testUserName")),
-//                                     NewField(fieldUserPassword, []byte(NegatedUserString([]byte("testPw")))),
-//                                     NewField(fieldUserAccess, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
-//                             },
-//                     ),
-//                     want: Transaction{
-//                             Fields: []Field{
-//                                     NewField(fieldError, []byte("Cannot create account guest because there is already an account with that login.")),
-//                             },
-//                     },
-//             },
-//     }
-//
-//     for _, test := range tests {
-//             if test.setup != nil {
-//                     test.setup()
-//             }
-//
-//             if err := srv.NewUser(test.account.Login, test.account.Name, NegatedUserString([]byte(test.account.Password)), test.account.Access); err != nil {
-//                     t.Errorf("%v", err)
-//             }
-//
-//             c := NewClient("")
-//             err := c.JoinServer(fmt.Sprintf(":%v", port), test.account.Login, test.account.Password)
-//             if err != nil {
-//                     t.Errorf("login failed: %v", err)
-//             }
-//
-//             if err := c.Send(test.request); err != nil {
-//                     t.Errorf("%v", err)
-//             }
-//
-//             tran := c.ReadTransactions()[0]
-//             for _, want := range test.want.Fields {
-//                     got := tran.GetField(want.Uint16ID())
-//                     if bytes.Compare(got.Data, want.Data) != 0 {
-//                             t.Errorf("%v: field mismatch:  want: %#v got: %#v", test.description, want.Data, got.Data)
-//                     }
-//             }
-//
-//             srv.DeleteUser(test.account.Login)
-//
-//             if test.teardown != nil {
-//                     test.teardown()
-//             }
-//     }
-//}
-//
-//func TestDeleteUser(t *testing.T) {
-//     srv, port := StartTestServer()
-//
-//     var tests = []transactionTest{
-//             {
-//                     description: "a deleteUser request from a user without the required access",
-//                     account: Account{
-//                             Login:    "test",
-//                             Name:     "unnamed",
-//                             Password: "test",
-//                             Access:   []byte{0, 0, 0, 0, 0, 0, 0, 0},
-//                     },
-//                     request: NewTransaction(
-//                             tranDeleteUser, 0,
-//                             []Field{
-//                                     NewField(fieldUserLogin, []byte(NegatedUserString([]byte("foo")))),
-//                             },
-//                     ),
-//                     want: Transaction{
-//                             Fields: []Field{
-//                                     NewField(fieldError, []byte("You are not allowed to delete accounts.")),
-//                             },
-//                     },
-//             },
-//             {
-//                     description: "a valid deleteUser request",
-//                     setup: func() {
-//                             _ = srv.NewUser("foo", "foo", "foo", []byte{0, 0, 0, 0, 0, 0, 0, 0})
-//                     },
-//                     account: Account{
-//                             Login:    "test",
-//                             Name:     "unnamed",
-//                             Password: "test",
-//                             Access:   []byte{255, 255, 255, 255, 255, 255, 255, 255},
-//                     },
-//                     request: NewTransaction(
-//                             tranDeleteUser, 0,
-//                             []Field{
-//                                     NewField(fieldUserLogin, []byte(NegatedUserString([]byte("foo")))),
-//                             },
-//                     ),
-//                     want: Transaction{
-//                             Fields: []Field{},
-//                     },
-//             },
-//     }
-//
-//     for _, test := range tests {
-//             test.Setup(srv)
-//
-//             c := NewClient("")
-//             err := c.JoinServer(fmt.Sprintf(":%v", port), test.account.Login, test.account.Password)
-//             if err != nil {
-//                     t.Errorf("login failed: %v", err)
-//             }
-//
-//             if err := c.Send(test.request); err != nil {
-//                     t.Errorf("%v", err)
-//             }
-//
-//             tran := c.ReadTransactions()[0]
-//             for _, want := range test.want.Fields {
-//                     got := tran.GetField(want.Uint16ID())
-//                     if bytes.Compare(got.Data, want.Data) != 0 {
-//                             t.Errorf("%v: field mismatch:  want: %#v got: %#v", test.description, want.Data, got.Data)
-//                     }
-//             }
-//
-//             test.Teardown(srv)
-//     }
-//}
-//
-//func TestDeleteFile(t *testing.T) {
-//     srv, port := StartTestServer()
-//
-//     var tests = []transactionTest{
-//             {
-//                     description: "a request without the required access",
-//                     account: Account{
-//                             Login:    "test",
-//                             Name:     "unnamed",
-//                             Password: "test",
-//                             Access:   []byte{0, 0, 0, 0, 0, 0, 0, 0},
-//                     },
-//                     request: NewTransaction(
-//                             tranDeleteFile, 0,
-//                             []Field{
-//                                     NewField(fieldFileName, []byte("testFile")),
-//                                     NewField(fieldFilePath, []byte("")),
-//                             },
-//                     ),
-//                     want: Transaction{
-//                             Fields: []Field{},
-//                     },
-//             },
-//             {
-//                     description: "a valid deleteFile request",
-//                     setup: func() {
-//                             _ = ioutil.WriteFile(srv.Config.FileRoot+"testFile", []byte{0x00}, 0666)
-//                     },
-//                     account: Account{
-//                             Login:    "test",
-//                             Name:     "unnamed",
-//                             Password: "test",
-//                             Access:   []byte{255, 255, 255, 255, 255, 255, 255, 255},
-//                     },
-//                     request: NewTransaction(
-//                             tranDeleteFile, 0,
-//                             []Field{
-//                                     NewField(fieldFileName, []byte("testFile")),
-//                                     NewField(fieldFilePath, []byte("")),
-//                             },
-//                     ),
-//                     want: Transaction{
-//                             Fields: []Field{},
-//                     },
-//             },
-//             {
-//                     description: "an invalid request for a file that does not exist",
-//                     account: Account{
-//                             Login:    "test",
-//                             Name:     "unnamed",
-//                             Password: "test",
-//                             Access:   []byte{255, 255, 255, 255, 255, 255, 255, 255},
-//                     },
-//                     request: NewTransaction(
-//                             tranDeleteFile, 0,
-//                             []Field{
-//                                     NewField(fieldFileName, []byte("testFile")),
-//                                     NewField(fieldFilePath, []byte("")),
-//                             },
-//                     ),
-//                     want: Transaction{
-//                             Fields: []Field{
-//                                     NewField(fieldError, []byte("Cannot delete file testFile because it does not exist or cannot be found.")),
-//                             },
-//                     },
-//             },
-//     }
-//
-//     for _, test := range tests {
-//             test.Setup(srv)
-//
-//             c := NewClient("")
-//
-//             if err := c.JoinServer(fmt.Sprintf(":%v", port), test.account.Login, test.account.Password); err != nil {
-//                     t.Errorf("login failed: %v", err)
-//             }
-//
-//             if err := c.Send(test.request); err != nil {
-//                     t.Errorf("%v", err)
-//             }
-//
-//             tran := c.ReadTransactions()[0]
-//             for _, want := range test.want.Fields {
-//                     got := tran.GetField(want.Uint16ID())
-//                     if bytes.Compare(got.Data, want.Data) != 0 {
-//                             t.Errorf("%v: field mismatch:  want: %#v got: %#v", test.description, want.Data, got.Data)
-//                     }
-//             }
-//
-//             test.Teardown(srv)
-//     }
-//}
-//
-//func Test_authorize(t *testing.T) {
-//     accessBitmap := big.NewInt(int64(0))
-//     accessBitmap.SetBit(accessBitmap, accessCreateFolder, 1)
-//     fmt.Printf("%v %b %x\n", accessBitmap, accessBitmap, accessBitmap)
-//     fmt.Printf("%b\n", 0b10000)
-//
-//     type args struct {
-//             access    *[]byte
-//             reqAccess int
-//     }
-//     tests := []struct {
-//             name string
-//             args args
-//             want bool
-//     }{
-//             {
-//                     name: "fooz",
-//                     args: args{
-//                             access: &[]byte{4, 0, 0, 0, 0, 0, 0, 0x02},
-//                             reqAccess: accessDownloadFile,
-//                     },
-//                     want: true,
-//             },
-//     }
-//     for _, tt := range tests {
-//             t.Run(tt.name, func(t *testing.T) {
-//                     if got := authorize(tt.args.access, tt.args.reqAccess); got != tt.want {
-//                             t.Errorf("authorize() = %v, want %v", got, tt.want)
-//                     }
-//             })
-//     }
-//}
+type mockReadWriter struct {
+       RBuf bytes.Buffer
+       WBuf *bytes.Buffer
+}
+
+func (mrw mockReadWriter) Read(p []byte) (n int, err error) {
+       return mrw.RBuf.Read(p)
+}
+
+func (mrw mockReadWriter) Write(p []byte) (n int, err error) {
+       return mrw.WBuf.Write(p)
+}
+
+func TestServer_handleFileTransfer(t *testing.T) {
+       type fields struct {
+               Port          int
+               Accounts      map[string]*Account
+               Agreement     []byte
+               Clients       map[uint16]*ClientConn
+               ThreadedNews  *ThreadedNews
+               fileTransfers map[[4]byte]*FileTransfer
+               Config        *Config
+               ConfigDir     string
+               Logger        *zap.SugaredLogger
+               PrivateChats  map[uint32]*PrivateChat
+               NextGuestID   *uint16
+               TrackerPassID [4]byte
+               Stats         *Stats
+               FS            FileStore
+               FlatNews      []byte
+       }
+       type args struct {
+               ctx context.Context
+               rwc io.ReadWriter
+       }
+       tests := []struct {
+               name     string
+               fields   fields
+               args     args
+               wantErr  assert.ErrorAssertionFunc
+               wantDump string
+       }{
+               {
+                       name: "with invalid protocol",
+                       args: args{
+                               ctx: func() context.Context {
+                                       ctx := context.Background()
+                                       ctx = context.WithValue(ctx, contextKeyReq, requestCtx{})
+                                       return ctx
+                               }(),
+                               rwc: func() io.ReadWriter {
+                                       mrw := mockReadWriter{}
+                                       mrw.WBuf = &bytes.Buffer{}
+                                       mrw.RBuf.Write(
+                                               []byte{
+                                                       0, 0, 0, 0,
+                                                       0, 0, 0, 5,
+                                                       0, 0, 0x01, 0,
+                                                       0, 0, 0, 0,
+                                               },
+                                       )
+                                       return mrw
+                               }(),
+                       },
+                       wantErr: assert.Error,
+               },
+               {
+                       name: "with invalid transfer ID",
+                       args: args{
+                               ctx: func() context.Context {
+                                       ctx := context.Background()
+                                       ctx = context.WithValue(ctx, contextKeyReq, requestCtx{})
+                                       return ctx
+                               }(),
+                               rwc: func() io.ReadWriter {
+                                       mrw := mockReadWriter{}
+                                       mrw.WBuf = &bytes.Buffer{}
+                                       mrw.RBuf.Write(
+                                               []byte{
+                                                       0x48, 0x54, 0x58, 0x46,
+                                                       0, 0, 0, 5,
+                                                       0, 0, 0x01, 0,
+                                                       0, 0, 0, 0,
+                                               },
+                                       )
+                                       return mrw
+                               }(),
+                       },
+                       wantErr: assert.Error,
+               },
+               {
+                       name: "file download",
+                       fields: fields{
+                               FS: &OSFileStore{},
+                               Config: &Config{
+                                       FileRoot: func() string {
+                                               path, _ := os.Getwd()
+                                               return path + "/test/config/Files"
+                                       }()},
+                               Logger: NewTestLogger(),
+                               Stats:  &Stats{},
+                               fileTransfers: map[[4]byte]*FileTransfer{
+                                       [4]byte{0, 0, 0, 5}: {
+                                               ReferenceNumber: []byte{0, 0, 0, 5},
+                                               Type:            FileDownload,
+                                               FileName:        []byte("testfile-8b"),
+                                               FilePath:        []byte{},
+                                               ClientConn: &ClientConn{
+                                                       Account: &Account{
+                                                               Login: "foo",
+                                                       },
+                                                       transfersMU: sync.Mutex{},
+                                                       transfers: map[int]map[[4]byte]*FileTransfer{
+                                                               FileDownload: {
+                                                                       [4]byte{0, 0, 0, 5}: &FileTransfer{},
+                                                               },
+                                                       },
+                                               },
+                                               bytesSentCounter: &WriteCounter{},
+                                       },
+                               },
+                       },
+                       args: args{
+                               ctx: func() context.Context {
+                                       ctx := context.Background()
+                                       ctx = context.WithValue(ctx, contextKeyReq, requestCtx{})
+                                       return ctx
+                               }(),
+                               rwc: func() io.ReadWriter {
+                                       mrw := mockReadWriter{}
+                                       mrw.WBuf = &bytes.Buffer{}
+                                       mrw.RBuf.Write(
+                                               []byte{
+                                                       0x48, 0x54, 0x58, 0x46,
+                                                       0, 0, 0, 5,
+                                                       0, 0, 0x01, 0,
+                                                       0, 0, 0, 0,
+                                               },
+                                       )
+                                       return mrw
+                               }(),
+                       },
+                       wantErr: assert.NoError,
+                       wantDump: `00000000  46 49 4c 50 00 01 00 00  00 00 00 00 00 00 00 00  |FILP............|
+00000010  00 00 00 00 00 00 00 02  49 4e 46 4f 00 00 00 00  |........INFO....|
+00000020  00 00 00 00 00 00 00 55  41 4d 41 43 54 45 58 54  |.......UAMACTEXT|
+00000030  54 54 58 54 00 00 00 00  00 00 01 00 00 00 00 00  |TTXT............|
+00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 0b  |................|
+00000070  74 65 73 74 66 69 6c 65  2d 38 62 00 00 44 41 54  |testfile-8b..DAT|
+00000080  41 00 00 00 00 00 00 00  00 00 00 00 08 7c 39 e0  |A............|9.|
+00000090  bc 64 e2 cd de 4d 41 43  52 00 00 00 00 00 00 00  |.d...MACR.......|
+000000a0  00 00 00 00 00                                    |.....|
+`,
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       s := &Server{
+                               Port:          tt.fields.Port,
+                               Accounts:      tt.fields.Accounts,
+                               Agreement:     tt.fields.Agreement,
+                               Clients:       tt.fields.Clients,
+                               ThreadedNews:  tt.fields.ThreadedNews,
+                               fileTransfers: tt.fields.fileTransfers,
+                               Config:        tt.fields.Config,
+                               ConfigDir:     tt.fields.ConfigDir,
+                               Logger:        tt.fields.Logger,
+                               Stats:         tt.fields.Stats,
+                               FS:            tt.fields.FS,
+                       }
+                       tt.wantErr(t, s.handleFileTransfer(tt.args.ctx, tt.args.rwc), fmt.Sprintf("handleFileTransfer(%v, %v)", tt.args.ctx, tt.args.rwc))
+
+                       assertTransferBytesEqual(t, tt.wantDump, tt.args.rwc.(mockReadWriter).WBuf.Bytes())
+               })
+       }
+}