diff --git a/node/chainSimulator/components/testOnlyProcessingNode.go b/node/chainSimulator/components/testOnlyProcessingNode.go index 14ec26cba86..8fe8fdaf6b6 100644 --- a/node/chainSimulator/components/testOnlyProcessingNode.go +++ b/node/chainSimulator/components/testOnlyProcessingNode.go @@ -220,7 +220,7 @@ func NewTestOnlyProcessingNode(args ArgsTestOnlyProcessingNode) (*testOnlyProces return nil, err } - err = instance.createBroadcastMessanger() + err = instance.createBroadcastMessenger() if err != nil { return nil, err } @@ -308,7 +308,7 @@ func (node *testOnlyProcessingNode) createNodesCoordinator(pref config.Preferenc return nil } -func (node *testOnlyProcessingNode) createBroadcastMessanger() error { +func (node *testOnlyProcessingNode) createBroadcastMessenger() error { broadcastMessenger, err := sposFactory.GetBroadcastMessenger( node.CoreComponentsHolder.InternalMarshalizer(), node.CoreComponentsHolder.Hasher(), diff --git a/node/chainSimulator/components/testOnlyProcessingNode_test.go b/node/chainSimulator/components/testOnlyProcessingNode_test.go index 64dbf32b8e3..6ee1620f888 100644 --- a/node/chainSimulator/components/testOnlyProcessingNode_test.go +++ b/node/chainSimulator/components/testOnlyProcessingNode_test.go @@ -1,17 +1,26 @@ package components import ( + "errors" + "math/big" "strings" "testing" "time" "github.com/multiversx/mx-chain-core-go/data/endProcess" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/node/chainSimulator/components/api" "github.com/multiversx/mx-chain-go/node/chainSimulator/configs" + "github.com/multiversx/mx-chain-go/node/chainSimulator/dtos" + "github.com/multiversx/mx-chain-go/testscommon/factory" + "github.com/multiversx/mx-chain-go/testscommon/state" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +var expectedErr = errors.New("expected error") + func createMockArgsTestOnlyProcessingNode(t *testing.T) ArgsTestOnlyProcessingNode { outputConfigs, err := configs.CreateChainSimulatorConfigs(configs.ArgsChainSimulatorConfigs{ NumOfShards: 3, @@ -37,24 +46,13 @@ func createMockArgsTestOnlyProcessingNode(t *testing.T) ArgsTestOnlyProcessingNo } func TestNewTestOnlyProcessingNode(t *testing.T) { - t.Parallel() - t.Run("should work", func(t *testing.T) { - if testing.Short() { - t.Skip("cannot run with -race -short; requires Wasm VM fix") - } - args := createMockArgsTestOnlyProcessingNode(t) node, err := NewTestOnlyProcessingNode(args) assert.Nil(t, err) assert.NotNil(t, node) }) - t.Run("try commit a block", func(t *testing.T) { - if testing.Short() { - t.Skip("cannot run with -race -short; requires Wasm VM fix") - } - args := createMockArgsTestOnlyProcessingNode(t) node, err := NewTestOnlyProcessingNode(args) assert.Nil(t, err) @@ -81,27 +79,370 @@ func TestNewTestOnlyProcessingNode(t *testing.T) { err = node.ProcessComponentsHolder.BlockProcessor().CommitBlock(header, block) assert.Nil(t, err) }) + t.Run("CreateCoreComponents failure should error", func(t *testing.T) { + args := createMockArgsTestOnlyProcessingNode(t) + args.Configs.GeneralConfig.Marshalizer.Type = "invalid type" + node, err := NewTestOnlyProcessingNode(args) + require.Error(t, err) + require.Nil(t, node) + }) + t.Run("CreateCryptoComponents failure should error", func(t *testing.T) { + args := createMockArgsTestOnlyProcessingNode(t) + args.Configs.GeneralConfig.PublicKeyPIDSignature.Type = "invalid type" + node, err := NewTestOnlyProcessingNode(args) + require.Error(t, err) + require.Nil(t, node) + }) + t.Run("CreateNetworkComponents failure should error", func(t *testing.T) { + args := createMockArgsTestOnlyProcessingNode(t) + args.SyncedBroadcastNetwork = nil + node, err := NewTestOnlyProcessingNode(args) + require.Error(t, err) + require.Nil(t, node) + }) + t.Run("CreateBootstrapComponents failure should error", func(t *testing.T) { + args := createMockArgsTestOnlyProcessingNode(t) + args.Configs.FlagsConfig.WorkingDir = "" + node, err := NewTestOnlyProcessingNode(args) + require.Error(t, err) + require.Nil(t, node) + }) + t.Run("CreateStateComponents failure should error", func(t *testing.T) { + args := createMockArgsTestOnlyProcessingNode(t) + args.ShardIDStr = common.MetachainShardName // coverage only + args.Configs.GeneralConfig.StateTriesConfig.MaxStateTrieLevelInMemory = 0 + node, err := NewTestOnlyProcessingNode(args) + require.Error(t, err) + require.Nil(t, node) + }) + t.Run("CreateProcessComponents failure should error", func(t *testing.T) { + args := createMockArgsTestOnlyProcessingNode(t) + args.Configs.FlagsConfig.Version = "" + node, err := NewTestOnlyProcessingNode(args) + require.Error(t, err) + require.Nil(t, node) + }) + t.Run("createFacade failure should error", func(t *testing.T) { + args := createMockArgsTestOnlyProcessingNode(t) + args.Configs.EpochConfig.GasSchedule.GasScheduleByEpochs = nil + node, err := NewTestOnlyProcessingNode(args) + require.Error(t, err) + require.Nil(t, node) + }) } -func TestOnlyProcessingNodeSetStateShouldError(t *testing.T) { - args := createMockArgsTestOnlyProcessingNode(t) - node, err := NewTestOnlyProcessingNode(args) - require.Nil(t, err) +func TestTestOnlyProcessingNode_SetKeyValueForAddress(t *testing.T) { + // TODO reinstate test after Wasm VM pointer fix + if testing.Short() { + t.Skip("cannot run with -race -short; requires Wasm VM fix") + } + + goodKeyValueMap := map[string]string{ + "01": "02", + } + node, err := NewTestOnlyProcessingNode(createMockArgsTestOnlyProcessingNode(t)) + require.NoError(t, err) address := "erd1qtc600lryvytxuy4h7vn7xmsy5tw6vuw3tskr75cwnmv4mnyjgsq6e5zgj" addressBytes, _ := node.CoreComponentsHolder.AddressPubKeyConverter().Decode(address) - keyValueMap := map[string]string{ - "nonHex": "01", + t.Run("should work", func(t *testing.T) { + _, err = node.StateComponentsHolder.AccountsAdapter().GetExistingAccount(addressBytes) + require.Error(t, err) + require.True(t, strings.Contains(err.Error(), "account was not found")) + + err = node.SetKeyValueForAddress(addressBytes, goodKeyValueMap) + require.NoError(t, err) + + _, err = node.StateComponentsHolder.AccountsAdapter().GetExistingAccount(addressBytes) + require.NoError(t, err) + }) + t.Run("decode key failure should error", func(t *testing.T) { + keyValueMap := map[string]string{ + "nonHex": "01", + } + err = node.SetKeyValueForAddress(addressBytes, keyValueMap) + require.NotNil(t, err) + require.True(t, strings.Contains(err.Error(), "cannot decode key")) + }) + t.Run("decode value failure should error", func(t *testing.T) { + keyValueMap := map[string]string{ + "01": "nonHex", + } + err = node.SetKeyValueForAddress(addressBytes, keyValueMap) + require.NotNil(t, err) + require.True(t, strings.Contains(err.Error(), "cannot decode value")) + }) + t.Run("LoadAccount failure should error", func(t *testing.T) { + argsLocal := createMockArgsTestOnlyProcessingNode(t) + nodeLocal, errLocal := NewTestOnlyProcessingNode(argsLocal) + require.NoError(t, errLocal) + + nodeLocal.StateComponentsHolder = &factory.StateComponentsMock{ + Accounts: &state.AccountsStub{ + LoadAccountCalled: func(container []byte) (vmcommon.AccountHandler, error) { + return nil, expectedErr + }, + }, + } + + errLocal = nodeLocal.SetKeyValueForAddress(addressBytes, nil) + require.Equal(t, expectedErr, errLocal) + }) + t.Run("account un-castable to UserAccountHandler should error", func(t *testing.T) { + argsLocal := createMockArgsTestOnlyProcessingNode(t) + nodeLocal, errLocal := NewTestOnlyProcessingNode(argsLocal) + require.NoError(t, errLocal) + + nodeLocal.StateComponentsHolder = &factory.StateComponentsMock{ + Accounts: &state.AccountsStub{ + LoadAccountCalled: func(container []byte) (vmcommon.AccountHandler, error) { + return &state.PeerAccountHandlerMock{}, nil + }, + }, + } + + errLocal = nodeLocal.SetKeyValueForAddress(addressBytes, nil) + require.Error(t, errLocal) + require.Equal(t, "cannot cast AccountHandler to UserAccountHandler", errLocal.Error()) + }) + t.Run("SaveKeyValue failure should error", func(t *testing.T) { + nodeLocal, errLocal := NewTestOnlyProcessingNode(createMockArgsTestOnlyProcessingNode(t)) + require.NoError(t, errLocal) + + nodeLocal.StateComponentsHolder = &factory.StateComponentsMock{ + Accounts: &state.AccountsStub{ + LoadAccountCalled: func(container []byte) (vmcommon.AccountHandler, error) { + return &state.UserAccountStub{ + SaveKeyValueCalled: func(key []byte, value []byte) error { + return expectedErr + }, + }, nil + }, + }, + } + + errLocal = nodeLocal.SetKeyValueForAddress(addressBytes, goodKeyValueMap) + require.Equal(t, expectedErr, errLocal) + }) + t.Run("SaveAccount failure should error", func(t *testing.T) { + argsLocal := createMockArgsTestOnlyProcessingNode(t) + nodeLocal, errLocal := NewTestOnlyProcessingNode(argsLocal) + require.NoError(t, errLocal) + + nodeLocal.StateComponentsHolder = &factory.StateComponentsMock{ + Accounts: &state.AccountsStub{ + SaveAccountCalled: func(account vmcommon.AccountHandler) error { + return expectedErr + }, + }, + } + + errLocal = nodeLocal.SetKeyValueForAddress(addressBytes, goodKeyValueMap) + require.Equal(t, expectedErr, errLocal) + }) +} + +func TestTestOnlyProcessingNode_SetStateForAddress(t *testing.T) { + // TODO reinstate test after Wasm VM pointer fix + if testing.Short() { + t.Skip("cannot run with -race -short; requires Wasm VM fix") } - err = node.SetKeyValueForAddress(addressBytes, keyValueMap) - require.NotNil(t, err) - require.True(t, strings.Contains(err.Error(), "cannot decode key")) - keyValueMap = map[string]string{ - "01": "nonHex", + node, err := NewTestOnlyProcessingNode(createMockArgsTestOnlyProcessingNode(t)) + require.NoError(t, err) + + address := "erd1qtc600lryvytxuy4h7vn7xmsy5tw6vuw3tskr75cwnmv4mnyjgsq6e5zgj" + scAddress := "erd1qqqqqqqqqqqqqpgqrchxzx5uu8sv3ceg8nx8cxc0gesezure5awqn46gtd" + addressBytes, _ := node.CoreComponentsHolder.AddressPubKeyConverter().Decode(address) + scAddressBytes, _ := node.CoreComponentsHolder.AddressPubKeyConverter().Decode(scAddress) + addressState := &dtos.AddressState{ + Address: "erd1qtc600lryvytxuy4h7vn7xmsy5tw6vuw3tskr75cwnmv4mnyjgsq6e5zgj", + Nonce: 100, + Balance: "1000000000000000000", + Keys: map[string]string{ + "01": "02", + }, } - err = node.SetKeyValueForAddress(addressBytes, keyValueMap) - require.NotNil(t, err) - require.True(t, strings.Contains(err.Error(), "cannot decode value")) + + t.Run("should work", func(t *testing.T) { + _, err = node.StateComponentsHolder.AccountsAdapter().GetExistingAccount(addressBytes) + require.Error(t, err) + require.True(t, strings.Contains(err.Error(), "account was not found")) + + err = node.SetStateForAddress(addressBytes, addressState) + require.NoError(t, err) + + account, err := node.StateComponentsHolder.AccountsAdapter().GetExistingAccount(addressBytes) + require.NoError(t, err) + require.Equal(t, addressState.Nonce, account.GetNonce()) + }) + t.Run("LoadAccount failure should error", func(t *testing.T) { + nodeLocal, errLocal := NewTestOnlyProcessingNode(createMockArgsTestOnlyProcessingNode(t)) + require.NoError(t, errLocal) + + nodeLocal.StateComponentsHolder = &factory.StateComponentsMock{ + Accounts: &state.AccountsStub{ + LoadAccountCalled: func(container []byte) (vmcommon.AccountHandler, error) { + return nil, expectedErr + }, + }, + } + + errLocal = nodeLocal.SetStateForAddress([]byte("address"), nil) + require.Equal(t, expectedErr, errLocal) + }) + t.Run("state balance invalid should error", func(t *testing.T) { + addressStateCopy := *addressState + addressStateCopy.Balance = "invalid balance" + err = node.SetStateForAddress(addressBytes, &addressStateCopy) + require.Error(t, err) + require.Equal(t, "cannot convert string balance to *big.Int", err.Error()) + }) + t.Run("AddToBalance failure should error", func(t *testing.T) { + nodeLocal, errLocal := NewTestOnlyProcessingNode(createMockArgsTestOnlyProcessingNode(t)) + require.NoError(t, errLocal) + + nodeLocal.StateComponentsHolder = &factory.StateComponentsMock{ + Accounts: &state.AccountsStub{ + LoadAccountCalled: func(container []byte) (vmcommon.AccountHandler, error) { + return &state.UserAccountStub{ + AddToBalanceCalled: func(value *big.Int) error { + return expectedErr + }, + }, nil + }, + }, + } + + errLocal = nodeLocal.SetStateForAddress([]byte("address"), addressState) + require.Equal(t, expectedErr, errLocal) + }) + t.Run("SaveKeyValue failure should error", func(t *testing.T) { + argsLocal := createMockArgsTestOnlyProcessingNode(t) + nodeLocal, errLocal := NewTestOnlyProcessingNode(argsLocal) + require.NoError(t, errLocal) + + nodeLocal.StateComponentsHolder = &factory.StateComponentsMock{ + Accounts: &state.AccountsStub{ + LoadAccountCalled: func(container []byte) (vmcommon.AccountHandler, error) { + return &state.UserAccountStub{ + SaveKeyValueCalled: func(key []byte, value []byte) error { + return expectedErr + }, + }, nil + }, + }, + } + + errLocal = nodeLocal.SetStateForAddress(addressBytes, addressState) + require.Equal(t, expectedErr, errLocal) + }) + t.Run("invalid sc code should error", func(t *testing.T) { + addressStateCopy := *addressState + addressStateCopy.Address = scAddress + addressStateCopy.Code = "invalid code" + + err = node.SetStateForAddress(scAddressBytes, &addressStateCopy) + require.Error(t, err) + }) + t.Run("invalid sc code hash should error", func(t *testing.T) { + addressStateCopy := *addressState + addressStateCopy.Address = scAddress + addressStateCopy.CodeHash = "invalid code hash" + + err = node.SetStateForAddress(scAddressBytes, &addressStateCopy) + require.Error(t, err) + }) + t.Run("invalid sc code metadata should error", func(t *testing.T) { + addressStateCopy := *addressState + addressStateCopy.Address = scAddress + addressStateCopy.CodeMetadata = "invalid code metadata" + + err = node.SetStateForAddress(scAddressBytes, &addressStateCopy) + require.Error(t, err) + }) + t.Run("invalid sc owner should error", func(t *testing.T) { + addressStateCopy := *addressState + addressStateCopy.Address = scAddress + addressStateCopy.Owner = "invalid owner" + + err = node.SetStateForAddress(scAddressBytes, &addressStateCopy) + require.Error(t, err) + }) + t.Run("invalid sc dev rewards should error", func(t *testing.T) { + addressStateCopy := *addressState + addressStateCopy.Owner = address + addressStateCopy.Address = scAddress + addressStateCopy.DeveloperRewards = "invalid dev rewards" + + err = node.SetStateForAddress(scAddressBytes, &addressStateCopy) + require.Error(t, err) + }) + t.Run("invalid root hash should error", func(t *testing.T) { + addressStateCopy := *addressState + addressStateCopy.Owner = address + addressStateCopy.Address = scAddress // coverage + addressStateCopy.DeveloperRewards = "1000000" + addressStateCopy.RootHash = "invalid root hash" + + err = node.SetStateForAddress(scAddressBytes, &addressStateCopy) + require.Error(t, err) + }) + t.Run("SaveAccount failure should error", func(t *testing.T) { + argsLocal := createMockArgsTestOnlyProcessingNode(t) + nodeLocal, errLocal := NewTestOnlyProcessingNode(argsLocal) + require.NoError(t, errLocal) + + nodeLocal.StateComponentsHolder = &factory.StateComponentsMock{ + Accounts: &state.AccountsStub{ + SaveAccountCalled: func(account vmcommon.AccountHandler) error { + return expectedErr + }, + }, + } + + errLocal = nodeLocal.SetStateForAddress(addressBytes, addressState) + require.Equal(t, expectedErr, errLocal) + }) +} + +func TestTestOnlyProcessingNode_IsInterfaceNil(t *testing.T) { + var node *testOnlyProcessingNode + require.True(t, node.IsInterfaceNil()) + + node, _ = NewTestOnlyProcessingNode(createMockArgsTestOnlyProcessingNode(t)) + require.False(t, node.IsInterfaceNil()) +} + +func TestTestOnlyProcessingNode_Close(t *testing.T) { + node, err := NewTestOnlyProcessingNode(createMockArgsTestOnlyProcessingNode(t)) + require.NoError(t, err) + + require.NoError(t, node.Close()) +} + +func TestTestOnlyProcessingNode_Getters(t *testing.T) { + node := &testOnlyProcessingNode{} + require.Nil(t, node.GetProcessComponents()) + require.Nil(t, node.GetChainHandler()) + require.Nil(t, node.GetBroadcastMessenger()) + require.Nil(t, node.GetCryptoComponents()) + require.Nil(t, node.GetCoreComponents()) + require.Nil(t, node.GetStateComponents()) + require.Nil(t, node.GetFacadeHandler()) + require.Nil(t, node.GetStatusCoreComponents()) + + node, err := NewTestOnlyProcessingNode(createMockArgsTestOnlyProcessingNode(t)) + require.Nil(t, err) + + require.NotNil(t, node.GetProcessComponents()) + require.NotNil(t, node.GetChainHandler()) + require.NotNil(t, node.GetBroadcastMessenger()) + require.NotNil(t, node.GetShardCoordinator()) + require.NotNil(t, node.GetCryptoComponents()) + require.NotNil(t, node.GetCoreComponents()) + require.NotNil(t, node.GetStateComponents()) + require.NotNil(t, node.GetFacadeHandler()) + require.NotNil(t, node.GetStatusCoreComponents()) } diff --git a/testscommon/state/userAccountStub.go b/testscommon/state/userAccountStub.go index 3e4278b2d38..ce54f059252 100644 --- a/testscommon/state/userAccountStub.go +++ b/testscommon/state/userAccountStub.go @@ -30,6 +30,7 @@ type UserAccountStub struct { RetrieveValueCalled func(_ []byte) ([]byte, uint32, error) SetDataTrieCalled func(dataTrie common.Trie) GetRootHashCalled func() []byte + SaveKeyValueCalled func(key []byte, value []byte) error } // HasNewCode - @@ -172,7 +173,10 @@ func (u *UserAccountStub) RetrieveValue(key []byte) ([]byte, uint32, error) { } // SaveKeyValue - -func (u *UserAccountStub) SaveKeyValue(_ []byte, _ []byte) error { +func (u *UserAccountStub) SaveKeyValue(key []byte, value []byte) error { + if u.SaveKeyValueCalled != nil { + return u.SaveKeyValueCalled(key, value) + } return nil }