X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/blobdiff_plain/aebc4d3647b9823ae8cbb57b21b1af83bfd011fb..854a92fc2755ace61c405df335ddf69b02a3d932:/hotline/server_test.go diff --git a/hotline/server_test.go b/hotline/server_test.go index 5937adc..bf608e1 100644 --- a/hotline/server_test.go +++ b/hotline/server_test.go @@ -1,805 +1,195 @@ 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 + outbox chan Transaction + mux sync.Mutex + flatNewsMux sync.Mutex + 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()) + }) + } +}