diff --git a/api/client_test.go b/api/client_test.go index 33a33d82db09d706372daf5632acf18dc5fdf5ac..e322b892d9845b007df0af1539b7f6731895afd9 100644 --- a/api/client_test.go +++ b/api/client_test.go @@ -7,7 +7,6 @@ package api import ( - "crypto/sha256" "github.com/golang/protobuf/proto" "gitlab.com/elixxir/client/cmixproto" "gitlab.com/elixxir/client/globals" @@ -15,7 +14,6 @@ import ( "gitlab.com/elixxir/client/keyStore" "gitlab.com/elixxir/client/parse" "gitlab.com/elixxir/client/user" - "gitlab.com/elixxir/comms/connect" "gitlab.com/elixxir/crypto/csprng" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/diffieHellman" @@ -32,115 +30,6 @@ import ( var TestKeySize = 768 -func TestRegistrationGob(t *testing.T) { - // Get a Client - testClient, err := NewClient(&globals.RamStorage{}, "", "", def) - if err != nil { - t.Error(err) - } - - err = testClient.InitNetwork() - if err != nil { - t.Error(err) - } - err = testClient.GenerateKeys(nil, "1234") - if err != nil { - t.Errorf("Could not generate Keys: %+v", err) - } - - // populate a gob in the store - _, err = testClient.RegisterWithPermissioning(true, "UAV6IWD6") - if err != nil { - t.Error(err) - } - - err = testClient.session.StoreSession() - if err != nil { - t.Error(err) - } - - // get the gob out of there again - Session, err := user.LoadSession(testClient.storage, - "1234") - if err != nil { - t.Error(err) - } - - VerifyRegisterGobUser(Session, t) - VerifyRegisterGobKeys(Session, testClient.topology, t) - - disconnectServers() -} - -//Happy path for a non precen user -func TestClient_Register(t *testing.T) { - //Make mock client - testClient, err := NewClient(&globals.RamStorage{}, "", "", def) - - if err != nil { - t.Error(err) - } - - err = testClient.InitNetwork() - if err != nil { - t.Error(err) - } - - err = testClient.GenerateKeys(nil, "password") - if err != nil { - t.Errorf("Could not generate Keys: %+v", err) - } - - // populate a gob in the store - _, err = testClient.RegisterWithPermissioning(true, "UAV6IWD6") - if err != nil { - t.Error(err) - } - - err = testClient.RegisterWithNodes() - if err != nil { - t.Error(err) - } - - // get the gob out of there again - Session, err := user.LoadSession(testClient.storage, - "password") - if err != nil { - t.Error(err) - } - - VerifyRegisterGobUser(Session, t) - - //Probs can't do this as there is now a sense of randomness?? - //VerifyRegisterGobKeys(Session, testClient.topology, t) - disconnectServers() -} - -func VerifyRegisterGobUser(session user.Session, t *testing.T) { - - expectedUser := id.NewUserFromUint(5, t) - - if reflect.DeepEqual(session.GetCurrentUser().User, &expectedUser) { - t.Errorf("Incorrect User ID; \n expected %q \n recieved: %q", - expectedUser, session.GetCurrentUser().User) - } -} - -func VerifyRegisterGobKeys(session user.Session, topology *connect.Circuit, t *testing.T) { - cmixGrp, _ := getGroups() - h := sha256.New() - h.Write([]byte(string(40005))) - expectedTransmissionBaseKey := cmixGrp.NewIntFromBytes(h.Sum(nil)) - - if session.GetNodeKeys(topology)[0].TransmissionKey.Cmp( - expectedTransmissionBaseKey) != 0 { - t.Errorf("Transmission base key was %v, expected %v", - session.GetNodeKeys(topology)[0].TransmissionKey.Text(16), - expectedTransmissionBaseKey.Text(16)) - } - -} - // Make sure that a formatted text message can deserialize to the text // message we would expect func TestFormatTextMessage(t *testing.T) { diff --git a/api/mockserver.go b/api/mockserver.go index c1c3b0ab04e041f0d92c28263b537a0d28771fbb..cf62d6f891a6d1d0f39f2e440f1fd2b93f035127 100644 --- a/api/mockserver.go +++ b/api/mockserver.go @@ -16,7 +16,9 @@ import ( "gitlab.com/elixxir/client/parse" pb "gitlab.com/elixxir/comms/mixmessages" "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/large" + "gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/id" "gitlab.com/elixxir/primitives/ndf" "sync" @@ -26,6 +28,7 @@ import ( var def *ndf.NetworkDefinition const InvalidClientVersion = "1.1.0" +const BatchSize = 10 // APIMessage are an implementation of the interface in bindings and API // easy to use from Go @@ -68,31 +71,31 @@ func (m APIMessage) Pack() []byte { } // Blank struct implementing ServerHandler interface for testing purposes (Passing to StartServer) -type TestInterface struct { +type GatewayHandler struct { LastReceivedMessage pb.Slot } // Returns message contents for MessageID, or a null/randomized message // if that ID does not exist of the same size as a regular message -func (m *TestInterface) GetMessage(userId *id.User, +func (m *GatewayHandler) GetMessage(userId *id.User, msgId, ipaddr string) (*pb.Slot, error) { return &pb.Slot{}, nil } // Return any MessageIDs in the globals for this User -func (m *TestInterface) CheckMessages(userId *id.User, +func (m *GatewayHandler) CheckMessages(userId *id.User, messageID, ipAddress string) ([]string, error) { return make([]string, 0), nil } // PutMessage adds a message to the outgoing queue and // calls SendBatch when it's size is the batch size -func (m *TestInterface) PutMessage(msg *pb.Slot, ipaddr string) error { +func (m *GatewayHandler) PutMessage(msg *pb.Slot, ipaddr string) error { m.LastReceivedMessage = *msg return nil } -func (m *TestInterface) ConfirmNonce(message *pb.RequestRegistrationConfirmation, ipaddr string) (*pb.RegistrationConfirmation, error) { +func (m *GatewayHandler) ConfirmNonce(message *pb.RequestRegistrationConfirmation, ipaddr string) (*pb.RegistrationConfirmation, error) { regConfirmation := &pb.RegistrationConfirmation{ ClientSignedByServer: &pb.RSASignature{}, } @@ -100,6 +103,58 @@ func (m *TestInterface) ConfirmNonce(message *pb.RequestRegistrationConfirmation return regConfirmation, nil } +// Pass-through for Registration Nonce Communication +func (m *GatewayHandler) RequestNonce(message *pb.NonceRequest, ipaddr string) (*pb.Nonce, error) { + dh := getDHPubKey().Bytes() + return &pb.Nonce{ + DHPubKey: dh, + }, nil +} + +//Blank struct that has an error path f +type GatewayHandlerMultipleMessages struct { + LastReceivedMessage []pb.Slot +} + +func (m *GatewayHandlerMultipleMessages) GetMessage(userId *id.User, + msgId, ipaddr string) (*pb.Slot, error) { + msg := []byte("Hello") + payload, err := e2e.Pad(msg, format.PayloadLen) + if err != nil { + fmt.Println("hello!") + } + return &pb.Slot{ + PayloadA: payload, + PayloadB: payload, + }, nil +} + +// Return any MessageIDs in the globals for this User +func (m *GatewayHandlerMultipleMessages) CheckMessages(userId *id.User, + messageID, ipaddr string) ([]string, error) { + msgs := []string{"a", "b", "c", "d", "e", "f", "g"} + return msgs, nil +} + +// PutMessage adds a message to the outgoing queue and +// calls SendBatch when it's size is the batch size +func (m *GatewayHandlerMultipleMessages) PutMessage(msg *pb.Slot, ipaddr string) error { + for i := 0; i < BatchSize; i++ { + msg.Index = uint32(i) + m.LastReceivedMessage = append(m.LastReceivedMessage, *msg) + } + return nil +} + +func (m *GatewayHandlerMultipleMessages) ConfirmNonce(message *pb.RequestRegistrationConfirmation, ipaddr string) (*pb.RegistrationConfirmation, error) { + return nil, nil +} + +// Pass-through for Registration Nonce Communication +func (m *GatewayHandlerMultipleMessages) RequestNonce(message *pb.NonceRequest, ipaddr string) (*pb.Nonce, error) { + return nil, nil +} + // Blank struct implementing Registration Handler interface for testing purposes (Passing to StartServer) type MockRegistration struct { //LastReceivedMessage pb.CmixMessage @@ -174,14 +229,6 @@ func getDHPubKey() *cyclic.Int { return cmixGrp.ExpG(dh, cmixGrp.NewMaxInt()) } -// Pass-through for Registration Nonce Communication -func (m *TestInterface) RequestNonce(message *pb.NonceRequest, ipaddr string) (*pb.Nonce, error) { - dh := getDHPubKey().Bytes() - return &pb.Nonce{ - DHPubKey: dh, - }, nil -} - // Mock dummy storage interface for testing. type DummyStorage struct { LocationA string @@ -251,7 +298,7 @@ func (s *MockPerm_NDF_ErrorCase) RegisterNode(ID []byte, return nil } -func (s *MockPerm_NDF_ErrorCase) GetUpdatedNDF(clientNdfHash []byte) ([]byte, error) { +func (s *MockPerm_NDF_ErrorCase) PollNdf(clientNdfHash []byte) ([]byte, error) { errMsg := fmt.Sprintf("Permissioning server does not have an ndf to give to client") return nil, errors.New(errMsg) } @@ -266,23 +313,23 @@ func (s *MockPerm_NDF_ErrorCase) GetCurrentClientVersion() (version string, err } //Mock Permissioning handler for error cases involving check version -type MockPerm_CheckVersion_ErrorCase struct { +type MockpermCheckversionErrorcase struct { } -func (s *MockPerm_CheckVersion_ErrorCase) RegisterNode(ID []byte, +func (s *MockpermCheckversionErrorcase) RegisterNode(ID []byte, NodeTLSCert, GatewayTLSCert, RegistrationCode, Addr, Addr2 string) error { return nil } -func (s *MockPerm_CheckVersion_ErrorCase) GetUpdatedNDF(clientNdfHash []byte) ([]byte, error) { - ndfData := buildMockNDF() +func (s *MockpermCheckversionErrorcase) PollNdf(clientNdfHash []byte) ([]byte, error) { + ndfData := def ndfJson, _ := json.Marshal(ndfData) return ndfJson, nil } -func (s *MockPerm_CheckVersion_ErrorCase) RegisterUser(registrationCode, +func (s *MockpermCheckversionErrorcase) RegisterUser(registrationCode, key string) (hash []byte, err error) { return nil, nil } -func (s *MockPerm_CheckVersion_ErrorCase) GetCurrentClientVersion() (version string, err error) { +func (s *MockpermCheckversionErrorcase) GetCurrentClientVersion() (version string, err error) { return globals.SEMVER, errors.New("Could not get version") } diff --git a/api/mockserver_test.go b/api/mockserver_test.go index ec95cb3d190ca5161806fd1b2bdecb2add6335b8..12b4ba42410b931fb43a052c8f92c722603f8ab7 100644 --- a/api/mockserver_test.go +++ b/api/mockserver_test.go @@ -18,28 +18,31 @@ import ( "gitlab.com/elixxir/primitives/ndf" "os" "testing" + "time" ) const NumNodes = 3 const NumGWs = NumNodes const RegPort = 5000 +const GWErrorPort = 7800 const GWsStartPort = 7900 const PermErrorServerPort = 4000 var RegHandler = MockRegistration{} var RegComms *registration.Comms +var NDFErrorReg = MockPerm_NDF_ErrorCase{} +var ErrorDef *ndf.NetworkDefinition const ValidRegCode = "UAV6IWD6" const InvalidRegCode = "INVALID_REG_CODE_" -var RegGWHandlers [3]*TestInterface = [NumGWs]*TestInterface{ +var RegGWHandlers [3]*GatewayHandler = [NumGWs]*GatewayHandler{ {LastReceivedMessage: pb.Slot{}}, {LastReceivedMessage: pb.Slot{}}, {LastReceivedMessage: pb.Slot{}}, } var GWComms [NumGWs]*gateway.Comms - -var errorDef *ndf.NetworkDefinition +var GWErrComms [NumGWs]*gateway.Comms // Setups general testing params and calls test wrapper func TestMain(m *testing.M) { @@ -51,11 +54,23 @@ func TestMain(m *testing.M) { os.Exit(testMainWrapper(m)) } -// Verify that a valid precanned user can register -func TestRegister_ValidPrecannedRegCodeReturnsZeroID(t *testing.T) { +func TestClient_StartMessageReceiver_MultipleMessages(t *testing.T) { // Initialize client with dummy storage + testDef := getNDF() + for i := 0; i < NumNodes; i++ { + gw := ndf.Gateway{ + Address: string(fmtAddress(GWErrorPort + i)), + } + testDef.Gateways = append(testDef.Gateways, gw) + GWErrComms[i] = gateway.StartGateway(gw.Address, + &GatewayHandlerMultipleMessages{}, nil, nil) + + } + + testDef.Nodes = def.Nodes + storage := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} - client, err := NewClient(&storage, "hello", "", def) + client, err := NewClient(&storage, "hello", "", testDef) if err != nil { t.Errorf("Failed to initialize dummy client: %s", err.Error()) } @@ -66,27 +81,50 @@ func TestRegister_ValidPrecannedRegCodeReturnsZeroID(t *testing.T) { if err != nil { t.Errorf("Client failed of connect: %+v", err) } - err = client.GenerateKeys(nil, "") + + err = client.GenerateKeys(nil, "password") if err != nil { t.Errorf("Could not generate Keys: %+v", err) } - // Register precanned user with all gateways - regRes, err := client.RegisterWithPermissioning(true, ValidRegCode) + // Register with a valid registration code + _, err = client.RegisterWithPermissioning(true, ValidRegCode) - // Verify registration succeeds with valid precanned registration code if err != nil { - t.Errorf("Registration failed: %s", err.Error()) + t.Errorf("Register failed: %s", err.Error()) } - if *regRes == *id.ZeroID { - t.Errorf("Invalid registration number received: %v", *regRes) + err = client.RegisterWithNodes() + if err != nil { + t.Error(err) } - disconnectServers() + + err = client.session.StoreSession() + if err != nil { + t.Errorf(err.Error()) + } + + // Login to gateway + _, err = client.Login("password") + + if err != nil { + t.Errorf("Login failed: %s", err.Error()) + } + + cb := func(err error) { + t.Log(err) + } + + err = client.StartMessageReceiver(cb) + + time.Sleep(3 * time.Second) + for _, gw := range GWErrComms { + gw.DisconnectAll() + } + } -// Verify that a valid precanned user can register -func TestRegister_ValidRegParams___(t *testing.T) { +func TestRegister_ValidPrecannedRegCodeReturnsZeroID(t *testing.T) { // Initialize client with dummy storage storage := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} client, err := NewClient(&storage, "hello", "", def) @@ -100,27 +138,22 @@ func TestRegister_ValidRegParams___(t *testing.T) { if err != nil { t.Errorf("Client failed of connect: %+v", err) } - err = client.GenerateKeys(nil, "") if err != nil { - t.Errorf("%+v", err) + t.Errorf("Could not generate Keys: %+v", err) } // Register precanned user with all gateways - regRes, err := client.RegisterWithPermissioning(false, ValidRegCode) + regRes, err := client.RegisterWithPermissioning(true, ValidRegCode) + + // Verify registration succeeds with valid precanned registration code if err != nil { t.Errorf("Registration failed: %s", err.Error()) } if *regRes == *id.ZeroID { - t.Errorf("Invalid registration number received: %+v", *regRes) - } - err = client.RegisterWithNodes() - if err != nil { - t.Error(err) + t.Errorf("Invalid registration number received: %v", *regRes) } - - //Disconnect and shutdown servers disconnectServers() } @@ -388,12 +421,12 @@ func TestLogout(t *testing.T) { func testMainWrapper(m *testing.M) int { def = getNDF() - errorDef = getNDF() + ErrorDef = getNDF() // Start mock registration server and defer its shutdown def.Registration = ndf.Registration{ Address: fmtAddress(RegPort), } - errorDef.Registration = ndf.Registration{ + ErrorDef.Registration = ndf.Registration{ Address: fmtAddress(PermErrorServerPort), } @@ -404,7 +437,7 @@ func testMainWrapper(m *testing.M) int { ID: nIdBytes, } def.Nodes = append(def.Nodes, n) - errorDef.Nodes = append(errorDef.Nodes, n) + ErrorDef.Nodes = append(ErrorDef.Nodes, n) } startServers() defer testWrapperShutdown() diff --git a/api/register_test.go b/api/register_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8cab5c728fe55b8bce8c10393ff1882e4154c01e --- /dev/null +++ b/api/register_test.go @@ -0,0 +1,214 @@ +package api + +import ( + "crypto/sha256" + "gitlab.com/elixxir/client/globals" + "gitlab.com/elixxir/client/user" + "gitlab.com/elixxir/comms/connect" + "gitlab.com/elixxir/primitives/id" + "reflect" + "testing" +) + +func TestRegistrationGob(t *testing.T) { + // Get a Client + testClient, err := NewClient(&globals.RamStorage{}, "", "", def) + if err != nil { + t.Error(err) + } + + err = testClient.InitNetwork() + if err != nil { + t.Error(err) + } + err = testClient.GenerateKeys(nil, "1234") + if err != nil { + t.Errorf("Could not generate Keys: %+v", err) + } + + // populate a gob in the store + _, err = testClient.RegisterWithPermissioning(true, "UAV6IWD6") + if err != nil { + t.Error(err) + } + + err = testClient.session.StoreSession() + if err != nil { + t.Error(err) + } + + // get the gob out of there again + Session, err := user.LoadSession(testClient.storage, + "1234") + if err != nil { + t.Error(err) + } + + VerifyRegisterGobUser(Session, t) + VerifyRegisterGobKeys(Session, testClient.topology, t) + + disconnectServers() +} + +//Happy path for a non precen user +func TestClient_Register(t *testing.T) { + //Make mock client + testClient, err := NewClient(&globals.RamStorage{}, "", "", def) + + if err != nil { + t.Error(err) + } + + err = testClient.InitNetwork() + if err != nil { + t.Error(err) + } + + err = testClient.GenerateKeys(nil, "password") + if err != nil { + t.Errorf("Could not generate Keys: %+v", err) + } + + // populate a gob in the store + _, err = testClient.RegisterWithPermissioning(true, "UAV6IWD6") + if err != nil { + t.Error(err) + } + + err = testClient.RegisterWithNodes() + if err != nil { + t.Error(err) + } + + // get the gob out of there again + Session, err := user.LoadSession(testClient.storage, + "password") + if err != nil { + t.Error(err) + } + + VerifyRegisterGobUser(Session, t) + + //Probs can't do this as there is now a sense of randomness?? + //VerifyRegisterGobKeys(Session, testClient.topology, t) + disconnectServers() +} + +func VerifyRegisterGobUser(session user.Session, t *testing.T) { + + expectedUser := id.NewUserFromUint(5, t) + + if reflect.DeepEqual(session.GetCurrentUser().User, &expectedUser) { + t.Errorf("Incorrect User ID; \n expected %q \n recieved: %q", + expectedUser, session.GetCurrentUser().User) + } +} + +func VerifyRegisterGobKeys(session user.Session, topology *connect.Circuit, t *testing.T) { + cmixGrp, _ := getGroups() + h := sha256.New() + h.Write([]byte(string(40005))) + expectedTransmissionBaseKey := cmixGrp.NewIntFromBytes(h.Sum(nil)) + + if session.GetNodeKeys(topology)[0].TransmissionKey.Cmp( + expectedTransmissionBaseKey) != 0 { + t.Errorf("Transmission base key was %v, expected %v", + session.GetNodeKeys(topology)[0].TransmissionKey.Text(16), + expectedTransmissionBaseKey.Text(16)) + } + +} + +/* +//TODO: Fix this test +//Error path: register with udb, but udb is not set up to return a message +func TestClient_RegisterWithUDB_NoUDB(t *testing.T) { + // Get a Client + testClient, err := NewClient(&globals.RamStorage{}, "", "", def) + if err != nil { + t.Error(err) + } + + err = testClient.InitNetwork() + if err != nil { + t.Error(err) + } + + err = testClient.GenerateKeys(nil, "password") + if err != nil { + t.Errorf("Failed to generate keys: %+v", err) + } + + // populate a gob in the store + _, err = testClient.RegisterWithPermissioning(true, ValidRegCode) + if err != nil { + t.Error(err) + } + + err = testClient.RegisterWithNodes() + if err != nil { + t.Error(err.Error()) + } + + // Login to gateway + _, err = testClient.Login("password") + + if err != nil { + t.Errorf("Login failed: %s", err.Error()) + } + cb := func(err error) { + t.Log(err) + } + + err = testClient.StartMessageReceiver(cb) + + if err != nil { + t.Errorf("Could not start message reception: %+v", err) + } + + err = testClient.RegisterWithUDB("test", 1 * time.Second) + if err != nil { + return + } + t.Errorf("Expected error path: should not successfully register with udb") +} +*/ + +// Verify that a valid precanned user can register +func TestRegister_ValidRegParams___(t *testing.T) { + // Initialize client with dummy storage + storage := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} + client, err := NewClient(&storage, "hello", "", def) + if err != nil { + t.Errorf("Failed to initialize dummy client: %s", err.Error()) + } + + // InitNetwork to gateways and reg server + err = client.InitNetwork() + + if err != nil { + t.Errorf("Client failed of connect: %+v", err) + } + + err = client.GenerateKeys(nil, "") + if err != nil { + t.Errorf("%+v", err) + } + + // Register precanned user with all gateways + regRes, err := client.RegisterWithPermissioning(false, ValidRegCode) + if err != nil { + t.Errorf("Registration failed: %s", err.Error()) + } + + if *regRes == *id.ZeroID { + t.Errorf("Invalid registration number received: %+v", *regRes) + } + err = client.RegisterWithNodes() + if err != nil { + t.Error(err) + } + + //Disconnect and shutdown servers + disconnectServers() +} diff --git a/bindings/client_test.go b/bindings/client_test.go index f96139679105ac83e23c91ca5bbbb4b0aaa9ccea..d1b851bb8d5896a243b5b2a8876a76826aef8d9c 100644 --- a/bindings/client_test.go +++ b/bindings/client_test.go @@ -16,6 +16,7 @@ import ( "gitlab.com/elixxir/client/cmixproto" "gitlab.com/elixxir/client/globals" "gitlab.com/elixxir/client/parse" + "gitlab.com/elixxir/client/user" "gitlab.com/elixxir/comms/gateway" "gitlab.com/elixxir/comms/registration" "gitlab.com/elixxir/crypto/signature/rsa" @@ -55,7 +56,7 @@ func (i *MockRegistration) RegisterNode(ID []byte, ServerAddr, ServerTlsCert, } func (i *MockRegistration) GetCurrentClientVersion() (string, error) { - return "0.1.0", nil + return globals.SEMVER, nil } func (i *MockRegistration) PollNdf(clientNdfHash []byte) ([]byte, error) { @@ -138,6 +139,219 @@ func (*DummyReceptionCallback) Callback(error) { return } +//Error path: Changing username should panic before registration has happened +func TestClient_ChangeUsername_ErrorPath(t *testing.T) { + defer func() { + if r := recover(); r != nil { + return + } + }() + ndfStr, pubKey := getNDFJSONStr(def, t) + + d := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} + + testClient, err := NewClient(&d, "hello", "", ndfStr, pubKey) + if err != nil { + t.Errorf("Failed to marshal group JSON: %s", err) + } + + err = testClient.InitNetwork() + if err != nil { + t.Errorf("Could not connect: %+v", err) + } + + err = testClient.ChangeUsername("josh420") + if err == nil { + t.Error("Expected error path, should not be able to change username before" + + "regState PermissioningComplete") + } +} + +//Happy path: should have no errors when changing username +func TestClient_ChangeUsername(t *testing.T) { + ndfStr, pubKey := getNDFJSONStr(def, t) + + d := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} + + testClient, err := NewClient(&d, "hello", "", ndfStr, pubKey) + if err != nil { + t.Errorf("Failed to marshal group JSON: %s", err) + } + + err = testClient.InitNetwork() + if err != nil { + t.Errorf("Could not connect: %+v", err) + } + + err = testClient.client.GenerateKeys(nil, "") + if err != nil { + t.Errorf("Could not generate Keys: %+v", err) + } + + regRes, err := testClient.RegisterWithPermissioning(false, ValidRegCode) + if len(regRes) == 0 { + t.Errorf("Invalid registration number received: %v", regRes) + } + + err = testClient.ChangeUsername("josh420") + if err != nil { + t.Errorf("Unexpected error, should have changed username: %v", err) + } + +} + +//Error path: Have added no contacts, so deleting a contact should fail +func TestDeleteUsername_EmptyContactList(t *testing.T) { + ndfStr, pubKey := getNDFJSONStr(def, t) + + d := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} + + testClient, err := NewClient(&d, "hello", "", ndfStr, pubKey) + if err != nil { + t.Errorf("Failed to marshal group JSON: %s", err) + } + + err = testClient.InitNetwork() + if err != nil { + t.Errorf("Could not connect: %+v", err) + } + + err = testClient.client.GenerateKeys(nil, "") + if err != nil { + t.Errorf("Could not generate Keys: %+v", err) + } + + regRes, err := testClient.RegisterWithPermissioning(false, ValidRegCode) + if len(regRes) == 0 { + t.Errorf("Invalid registration number received: %v", regRes) + } + //Attempt to delete a contact from an empty contact list + _, err = testClient.DeleteContact([]byte("typo")) + if err != nil { + return + } + t.Errorf("Expected error path, but did not get error on deleting a contact." + + "Contact list should be empty") +} + +func TestClient_GetRegState(t *testing.T) { + ndfStr, pubKey := getNDFJSONStr(def, t) + + d := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} + testClient, err := NewClient(&d, "hello", "", ndfStr, pubKey) + if err != nil { + t.Errorf("Failed to marshal group JSON: %s", err) + } + + err = testClient.InitNetwork() + if err != nil { + t.Errorf("Could not connect: %+v", err) + } + + err = testClient.client.GenerateKeys(nil, "") + if err != nil { + t.Errorf("Could not generate Keys: %+v", err) + } + + // Register with a valid registration code + _, err = testClient.RegisterWithPermissioning(true, ValidRegCode) + + if err != nil { + t.Errorf("Register with permissioning failed: %s", err.Error()) + } + + if testClient.GetRegState() != int64(user.PermissioningComplete) { + t.Errorf("Unexpected reg state: Expected PermissioningComplete (%d), recieved: %d", + user.PermissioningComplete, testClient.GetRegState()) + } + + err = testClient.RegisterWithNodes() + if err != nil { + t.Errorf("Register with nodes failed: %v", err.Error()) + } + +} + +//Happy path: send unencrypted message +func TestClient_Send(t *testing.T) { + ndfStr, pubKey := getNDFJSONStr(def, t) + + d := DummyStorage{LocationA: "Blah", StoreA: []byte{'a', 'b', 'c'}} + testClient, err := NewClient(&d, "hello", "", ndfStr, pubKey) + + if err != nil { + t.Errorf("Failed to marshal group JSON: %s", err) + } + + err = testClient.InitNetwork() + if err != nil { + t.Errorf("Could not connect: %+v", err) + } + + err = testClient.client.GenerateKeys(nil, "password") + if err != nil { + t.Errorf("Could not generate Keys: %+v", err) + } + + // Register with a valid registration code + userID, err := testClient.RegisterWithPermissioning(true, ValidRegCode) + + if err != nil { + t.Errorf("Register with permissioning failed: %s", err.Error()) + } + + err = testClient.RegisterWithNodes() + if err != nil { + t.Errorf("Register with nodes failed: %v", err.Error()) + } + + // Login to gateway + _, err = testClient.Login(userID, "password") + + if err != nil { + t.Errorf("Login failed: %s", err.Error()) + } + + err = testClient.StartMessageReceiver(&DummyReceptionCallback{}) + + if err != nil { + t.Errorf("Could not start message reception: %+v", err) + } + + // Test send with invalid sender ID + err = testClient.Send( + mockMesssage{ + Sender: id.NewUserFromUint(12, t), + TypedBody: parse.TypedBody{Body: []byte("test")}, + Receiver: id.NewUserFromBytes(userID), + }, false) + + if err != nil { + // TODO: would be nice to catch the sender but we + // don't have the interface/mocking for that. + t.Errorf("error on first message send: %+v", err) + } + + // Test send with valid inputs + err = testClient.Send( + mockMesssage{ + Sender: id.NewUserFromBytes(userID), + TypedBody: parse.TypedBody{Body: []byte("test")}, + Receiver: testClient.client.GetCurrentUser(), + }, false) + + if err != nil { + t.Errorf("Error sending message: %v", err) + } + + err = testClient.Logout() + + if err != nil { + t.Errorf("Logout failed: %v", err) + } + disconnectServers() +} + func TestLoginLogout(t *testing.T) { ndfStr, pubKey := getNDFJSONStr(def, t) @@ -489,3 +703,52 @@ func (d *DummyStorage) LoadA() []byte { func (d *DummyStorage) LoadB() []byte { return d.StoreB } + +type mockMesssage struct { + parse.TypedBody + // The crypto type is inferred from the message's contents + InferredType parse.CryptoType + Sender *id.User + Receiver *id.User + Nonce []byte + Timestamp time.Time +} + +// Returns the message's sender ID +func (m mockMesssage) GetSender() []byte { + return m.Sender.Bytes() +} + +// Returns the message payload +// Parse this with protobuf/whatever according to the type of the message +func (m mockMesssage) GetPayload() []byte { + return m.TypedBody.Body +} + +// Returns the message's recipient ID +func (m mockMesssage) GetRecipient() []byte { + return m.Receiver.Bytes() +} + +// Returns the message's type +func (m mockMesssage) GetMessageType() int32 { + return m.TypedBody.MessageType +} + +// Returns the message's timestamp in seconds since unix epoc +func (m mockMesssage) GetTimestamp() int64 { + return m.Timestamp.Unix() +} + +// Returns the message's timestamp in ns since unix epoc +func (m mockMesssage) GetTimestampNano() int64 { + return m.Timestamp.UnixNano() +} + +func disconnectServers() { + for _, gw := range GWComms { + gw.DisconnectAll() + + } + RegComms.DisconnectAll() +} diff --git a/globals/storage.go b/globals/storage.go index 3170379add12b914d56fc6eb192e1944df84c758..aecd54789a000a50eb0fc766db9937a8cd00f6a3 100644 --- a/globals/storage.go +++ b/globals/storage.go @@ -49,9 +49,9 @@ func (ds *DefaultStorage) GetLocation() (string, string) { func (ds *DefaultStorage) IsEmpty() bool { _, err := os.Stat(ds.locationA) - firstEmpty := err != nil && !os.IsNotExist(err) + firstEmpty := err != nil && os.IsNotExist(err) _, err = os.Stat(ds.locationB) - secondEmpty := err != nil && !os.IsNotExist(err) + secondEmpty := err != nil && os.IsNotExist(err) return firstEmpty && secondEmpty } diff --git a/globals/storage_test.go b/globals/storage_test.go index a9655612f2249844e13a645198d4ba1855fd8009..d1f48943c3c706bbac1296caa7e432f8ab74cf84 100644 --- a/globals/storage_test.go +++ b/globals/storage_test.go @@ -20,6 +20,11 @@ func TestInitStorage(t *testing.T) { // Test DefaultStorage initialization without existing storage storage := &DefaultStorage{} + //Check that storage is empty prior to any Save calls + if !storage.IsEmpty() { + t.Errorf("ds.IsEmpty failed to detect an empty storage") + } + storage.SetLocation(TestSaveLocA, TestSaveLocB) // Test DS saveA @@ -33,6 +38,10 @@ func TestInitStorage(t *testing.T) { t.Errorf("ds.Save failed to create a save file A at: %v", TestSaveLocA) } + //Check that the storage is not empty after a saveA call + if storage.IsEmpty() { + t.Errorf("ds.IsEmpty failed to detect a non-empty storage") + } // Test DS loadA actualData := storage.LoadA()