From e472274ffab046509a83d7823cc98f8de80611b8 Mon Sep 17 00:00:00 2001 From: josh <josh@elixxir.io> Date: Tue, 20 Apr 2021 10:54:32 -0700 Subject: [PATCH] Add testing for new functions --- network/gateway/hostpool_test.go | 153 ++++++++++++++++++- network/gateway/sender_test.go | 251 +++++++++++++++++++++++++++++++ network/gateway/utils_test.go | 42 ++++++ 3 files changed, 442 insertions(+), 4 deletions(-) create mode 100644 network/gateway/sender_test.go diff --git a/network/gateway/hostpool_test.go b/network/gateway/hostpool_test.go index 1f3ffcc7c..9e48d9ae5 100644 --- a/network/gateway/hostpool_test.go +++ b/network/gateway/hostpool_test.go @@ -8,6 +8,7 @@ package gateway import ( + "fmt" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/comms/network" @@ -250,8 +251,152 @@ func TestHostPool_ReplaceHost_Error(t *testing.T) { } +// Unit test +func TestHostPool_ForceReplace(t *testing.T) { + manager := newMockManager() + rng := csprng.NewSystemRNG() + testNdf := getTestNdf(t) + testStorage := storage.InitTestingSession(t) + addGwChan := make(chan network.NodeGateway) + + // Construct custom params + params := DefaultPoolParams() + params.PoolSize = uint32(len(testNdf.Gateways)) + + // Pull all gateways from ndf into host manager + for _, gw := range testNdf.Gateways { + + gwId, err := id.Unmarshal(gw.ID) + if err != nil { + t.Errorf("Failed to unmarshal ID in mock ndf: %v", err) + } + // Add mock gateway to manager + _, err = manager.AddHost(gwId, gw.Address, nil, connect.GetDefaultHostParams()) + if err != nil { + t.Errorf("Could not add mock host to manager: %v", err) + t.FailNow() + } + + } + + // Call the constructor + testPool, err := newHostPool(params, rng, testNdf, manager, + testStorage, addGwChan) + if err != nil { + t.Fatalf("Failed to create mock host pool: %v", err) + } + + // Add all gateways to hostPool's map + for index, gw := range testNdf.Gateways { + gwId, err := id.Unmarshal(gw.ID) + if err != nil { + t.Fatalf("Failed to unmarshal ID in mock ndf: %v", err) + } + + err = testPool.replaceHost(gwId, uint32(index)) + if err != nil { + t.Fatalf("Failed to replace host in set-up: %v", err) + } + } + + oldGatewayIndex := 0 + oldHost := testPool.hostList[oldGatewayIndex] + + // Force replace the gateway at a given index + err = testPool.forceReplace(uint32(oldGatewayIndex)) + if err != nil { + t.Errorf("Failed to force replace: %v", err) + } + + // Ensure that old gateway has been removed from the map + if _, ok := testPool.hostMap[*oldHost.GetId()]; ok { + t.Errorf("Expected old host to be removed from map") + } + + // Ensure we are disconnected from the old host + if isConnected, _ := oldHost.Connected(); isConnected { + t.Errorf("Failed to disconnect from old host %s", oldHost) + } + +} + +// Unit test +func TestHostPool_CheckReplace(t *testing.T) { + manager := newMockManager() + rng := csprng.NewSystemRNG() + testNdf := getTestNdf(t) + testStorage := storage.InitTestingSession(t) + addGwChan := make(chan network.NodeGateway) + + // Construct custom params + params := DefaultPoolParams() + params.PoolSize = uint32(len(testNdf.Gateways)) - 5 + + // Pull all gateways from ndf into host manager + for _, gw := range testNdf.Gateways { + + gwId, err := id.Unmarshal(gw.ID) + if err != nil { + t.Errorf("Failed to unmarshal ID in mock ndf: %v", err) + } + // Add mock gateway to manager + _, err = manager.AddHost(gwId, gw.Address, nil, connect.GetDefaultHostParams()) + if err != nil { + t.Errorf("Could not add mock host to manager: %v", err) + t.FailNow() + } + + } + + // Call the constructor + testPool, err := newHostPool(params, rng, testNdf, manager, + testStorage, addGwChan) + if err != nil { + t.Fatalf("Failed to create mock host pool: %v", err) + } + + // Call check replace + oldGatewayIndex := 0 + oldHost := testPool.hostList[oldGatewayIndex] + expectedError := fmt.Errorf(errorsList[0]) + err = testPool.checkReplace(oldHost.GetId(), expectedError) + if err != nil { + t.Errorf("Failed to check replace: %v", err) + } + + // Ensure that old gateway has been removed from the map + if _, ok := testPool.hostMap[*oldHost.GetId()]; ok { + t.Errorf("Expected old host to be removed from map") + } + + // Ensure we are disconnected from the old host + if isConnected, _ := oldHost.Connected(); isConnected { + t.Errorf("Failed to disconnect from old host %s", oldHost) + } + + // Check that an error not in the global list results in a no-op + goodGatewayIndex := 0 + goodGateway := testPool.hostList[goodGatewayIndex] + unexpectedErr := fmt.Errorf("Not in global error list") + err = testPool.checkReplace(oldHost.GetId(), unexpectedErr) + if err != nil { + t.Errorf("Failed to check replace: %v", err) + } + + // Ensure that gateway with an unexpected error was not modified + if _, ok := testPool.hostMap[*goodGateway.GetId()]; !ok { + t.Errorf("Expected gateway with non-expected error to not be modified") + } + + // Ensure gateway host has not been disconnected + if isConnected, _ := oldHost.Connected(); isConnected { + t.Errorf("Should not disconnect from %s", oldHost) + } + +} + // TODO: Adapt to new methods -//// Happy path +// Happy path //func TestHostPool_PruneHostPool(t *testing.T) { // manager := newMockManager() // testNdf := getTestNdf(t) @@ -544,7 +689,7 @@ func TestHostPool_ForceAdd(t *testing.T) { testPool, err := newHostPool(params, rng, testNdf, manager, testStorage, addGwChan) if err != nil { - t.Errorf("Failed to create mock host pool: %v", err) + t.Fatalf("Failed to create mock host pool: %v", err) } // Construct a list of new gateways to add @@ -555,8 +700,7 @@ func TestHostPool_ForceAdd(t *testing.T) { // Add mock gateway to manager _, err = manager.AddHost(gwId, "", nil, connect.GetDefaultHostParams()) if err != nil { - t.Errorf("Could not add mock host to manager: %v", err) - t.FailNow() + t.Fatalf("Could not add mock host to manager: %v", err) } newGateways[i] = gwId } @@ -567,6 +711,7 @@ func TestHostPool_ForceAdd(t *testing.T) { t.Errorf("Could not add gateways: %v", err) } + // check that gateways have been added to the map for _, gw := range newGateways { if _, ok := testPool.hostMap[*gw]; !ok { t.Errorf("Failed to forcefully add new gateway ID: %v", gw) diff --git a/network/gateway/sender_test.go b/network/gateway/sender_test.go new file mode 100644 index 000000000..5b4d50e27 --- /dev/null +++ b/network/gateway/sender_test.go @@ -0,0 +1,251 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// + +package gateway + +import ( + "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/comms/network" + "gitlab.com/xx_network/comms/connect" + "gitlab.com/xx_network/crypto/csprng" + "gitlab.com/xx_network/primitives/id" + "reflect" + "testing" +) + +// Unit test +func TestNewSender(t *testing.T) { + manager := newMockManager() + rng := csprng.NewSystemRNG() + testNdf := getTestNdf(t) + testStorage := storage.InitTestingSession(t) + addGwChan := make(chan network.NodeGateway) + params := DefaultPoolParams() + params.PoolSize = uint32(len(testNdf.Gateways)) + + _, err := NewSender(params, rng, testNdf, manager, testStorage, addGwChan) + if err != nil { + t.Fatalf("Failed to create mock sender: %v", err) + } +} + +// Unit test +func TestSender_SendToAny(t *testing.T) { + manager := newMockManager() + rng := csprng.NewSystemRNG() + testNdf := getTestNdf(t) + testStorage := storage.InitTestingSession(t) + addGwChan := make(chan network.NodeGateway) + params := DefaultPoolParams() + params.PoolSize = uint32(len(testNdf.Gateways)) + + // Pull all gateways from ndf into host manager + for _, gw := range testNdf.Gateways { + + gwId, err := id.Unmarshal(gw.ID) + if err != nil { + t.Errorf("Failed to unmarshal ID in mock ndf: %v", err) + } + // Add mock gateway to manager + _, err = manager.AddHost(gwId, gw.Address, nil, connect.GetDefaultHostParams()) + if err != nil { + t.Errorf("Could not add mock host to manager: %v", err) + t.FailNow() + } + + } + + sender, err := NewSender(params, rng, testNdf, manager, testStorage, addGwChan) + if err != nil { + t.Fatalf("Failed to create mock sender: %v", err) + } + + // Add all gateways to hostPool's map + for index, gw := range testNdf.Gateways { + gwId, err := id.Unmarshal(gw.ID) + if err != nil { + t.Fatalf("Failed to unmarshal ID in mock ndf: %v", err) + } + + err = sender.replaceHost(gwId, uint32(index)) + if err != nil { + t.Fatalf("Failed to replace host in set-up: %v", err) + } + } + + // Test sendToAny with test interfaces + result, err := sender.SendToAny(SendToAny_HappyPath) + if err != nil { + t.Errorf("Should not error in SendToAny happy path: %v", err) + } + + if !reflect.DeepEqual(result, happyPathReturn) { + t.Errorf("Expected result not returnev via SendToAny interface."+ + "\n\tExpected: %v"+ + "\n\tReceived: %v", happyPathReturn, result) + } + + _, err = sender.SendToAny(SendToAny_KnownError) + if err == nil { + t.Fatalf("Expected error path did not receive error") + } + + _, err = sender.SendToAny(SendToAny_UnknownError) + if err == nil { + t.Fatalf("Expected error path did not receive error") + } + +} + +// Unit test +func TestSender_SendToPreferred(t *testing.T) { + manager := newMockManager() + rng := csprng.NewSystemRNG() + testNdf := getTestNdf(t) + testStorage := storage.InitTestingSession(t) + addGwChan := make(chan network.NodeGateway) + params := DefaultPoolParams() + params.PoolSize = uint32(len(testNdf.Gateways)) - 5 + + // Do not test proxy attempts code in this test + // (self contain to code specific in sendPreferred) + params.ProxyAttempts = 0 + + // Pull all gateways from ndf into host manager + for _, gw := range testNdf.Gateways { + + gwId, err := id.Unmarshal(gw.ID) + if err != nil { + t.Errorf("Failed to unmarshal ID in mock ndf: %v", err) + } + // Add mock gateway to manager + _, err = manager.AddHost(gwId, gw.Address, nil, connect.GetDefaultHostParams()) + if err != nil { + t.Errorf("Could not add mock host to manager: %v", err) + t.FailNow() + } + + } + + sender, err := NewSender(params, rng, testNdf, manager, testStorage, addGwChan) + if err != nil { + t.Fatalf("Failed to create mock sender: %v", err) + } + + preferredIndex := 0 + preferredHost := sender.hostList[preferredIndex] + + // Happy path + result, err := sender.SendToPreferred([]*id.ID{preferredHost.GetId()}, SendToPreferred_HappyPath) + if err != nil { + t.Errorf("Should not error in SendToPreferred happy path: %v", err) + } + + if !reflect.DeepEqual(result, happyPathReturn) { + t.Errorf("Expected result not returnev via SendToPreferred interface."+ + "\n\tExpected: %v"+ + "\n\tReceived: %v", happyPathReturn, result) + } + + // Call a send which returns an error which triggers replacement + _, err = sender.SendToPreferred([]*id.ID{preferredHost.GetId()}, SendToPreferred_KnownError) + if err == nil { + t.Fatalf("Expected error path did not receive error") + } + + // Check the host has been replaced + if _, ok := sender.hostMap[*preferredHost.GetId()]; ok { + t.Errorf("Expected host %s to be removed due to error", preferredHost) + } + + // Ensure we are disconnected from the old host + if isConnected, _ := preferredHost.Connected(); isConnected { + t.Errorf("ForceReplace error: Failed to disconnect from old host %s", preferredHost) + } + + // Get a new host to test on + preferredIndex = 4 + preferredHost = sender.hostList[preferredIndex] + + // Unknown error return will not trigger replacement + _, err = sender.SendToPreferred([]*id.ID{preferredHost.GetId()}, SendToPreferred_UnknownError) + if err == nil { + t.Fatalf("Expected error path did not receive error") + } + + // Check the host has not been replaced + if _, ok := sender.hostMap[*preferredHost.GetId()]; !ok { + t.Errorf("Host %s should not have been removed due on an unknown error", preferredHost) + } + + // Ensure we are disconnected from the old host + if isConnected, _ := preferredHost.Connected(); isConnected { + t.Errorf("Should not disconnect from %s", preferredHost) + } + +} + +func TestSender_SendToSpecific(t *testing.T) { + manager := newMockManager() + rng := csprng.NewSystemRNG() + testNdf := getTestNdf(t) + testStorage := storage.InitTestingSession(t) + addGwChan := make(chan network.NodeGateway) + params := DefaultPoolParams() + params.PoolSize = uint32(len(testNdf.Gateways)) - 5 + + // Do not test proxy attempts code in this test + // (self contain to code specific in sendPreferred) + params.ProxyAttempts = 0 + + // Pull all gateways from ndf into host manager + for _, gw := range testNdf.Gateways { + + gwId, err := id.Unmarshal(gw.ID) + if err != nil { + t.Errorf("Failed to unmarshal ID in mock ndf: %v", err) + } + // Add mock gateway to manager + _, err = manager.AddHost(gwId, gw.Address, nil, connect.GetDefaultHostParams()) + if err != nil { + t.Errorf("Could not add mock host to manager: %v", err) + t.FailNow() + } + + } + + sender, err := NewSender(params, rng, testNdf, manager, testStorage, addGwChan) + if err != nil { + t.Fatalf("Failed to create mock sender: %v", err) + } + + preferredIndex := 0 + preferredHost := sender.hostList[preferredIndex] + + // Happy path + result, err := sender.SendToSpecific(preferredHost.GetId(), SendToSpecific_HappyPath) + if err != nil { + t.Errorf("Should not error in SendToSpecific happy path: %v", err) + } + + if !reflect.DeepEqual(result, happyPathReturn) { + t.Errorf("Expected result not returnev via SendToSpecific interface."+ + "\n\tExpected: %v"+ + "\n\tReceived: %v", happyPathReturn, result) + } + + // Ensure host is now in map + if _, ok := sender.hostMap[*preferredHost.GetId()]; !ok { + t.Errorf("Failed to forcefully add new gateway ID: %v", preferredHost.GetId()) + } + + _, err = sender.SendToSpecific(preferredHost.GetId(), SendToSpecific_Abort) + if err == nil { + t.Errorf("Expected sendSpecific to return an abort") + } + +} diff --git a/network/gateway/utils_test.go b/network/gateway/utils_test.go index 9cb76c783..0ec7dc11f 100644 --- a/network/gateway/utils_test.go +++ b/network/gateway/utils_test.go @@ -1,6 +1,14 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// + package gateway import ( + "fmt" "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/ndf" @@ -118,3 +126,37 @@ func getTestNdf(face interface{}) *ndf.NetworkDefinition { }}, } } + +const happyPathReturn = "happyPathReturn" + +func SendToPreferred_HappyPath(host *connect.Host, target *id.ID) (interface{}, error) { + return happyPathReturn, nil +} + +func SendToPreferred_KnownError(host *connect.Host, target *id.ID) (interface{}, error) { + return nil, fmt.Errorf(errorsList[0]) +} + +func SendToPreferred_UnknownError(host *connect.Host, target *id.ID) (interface{}, error) { + return nil, fmt.Errorf("Unexpected error: Oopsie") +} + +func SendToAny_HappyPath(host *connect.Host) (interface{}, error) { + return happyPathReturn, nil +} + +func SendToAny_KnownError(host *connect.Host) (interface{}, error) { + return nil, fmt.Errorf(errorsList[0]) +} + +func SendToAny_UnknownError(host *connect.Host) (interface{}, error) { + return nil, fmt.Errorf("Unexpected error: Oopsie") +} + +func SendToSpecific_HappyPath(host *connect.Host, target *id.ID) (interface{}, bool, error) { + return happyPathReturn, false, nil +} + +func SendToSpecific_Abort(host *connect.Host, target *id.ID) (interface{}, bool, error) { + return nil, true, fmt.Errorf(errorsList[0]) +} -- GitLab