x/evm: state_object tests (#388)

* x/evm: state_object tests

* tests

* commit tests

* finalize tests

* update
This commit is contained in:
Federico Kunze 2020-07-13 19:44:28 +02:00 committed by GitHub
parent fef16af382
commit 42fc796595
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 247 additions and 4 deletions

View File

@ -0,0 +1,117 @@
package types_test
import (
"math/big"
ethcmn "github.com/ethereum/go-ethereum/common"
)
func (suite *StateDBTestSuite) TestStateObject_State() {
testCase := []struct {
name string
key ethcmn.Hash
expValue ethcmn.Hash
malleate func()
}{
{
"no set value, load from KVStore",
ethcmn.BytesToHash([]byte("key")),
ethcmn.Hash{},
func() {},
},
{
"no-op SetState",
ethcmn.BytesToHash([]byte("key")),
ethcmn.Hash{},
func() {
suite.stateObject.SetState(nil, ethcmn.BytesToHash([]byte("key")), ethcmn.Hash{})
},
},
{
"cached value",
ethcmn.BytesToHash([]byte("key1")),
ethcmn.BytesToHash([]byte("value1")),
func() {
suite.stateObject.SetState(nil, ethcmn.BytesToHash([]byte("key1")), ethcmn.BytesToHash([]byte("value1")))
},
},
}
for _, tc := range testCase {
tc.malleate()
value := suite.stateObject.GetState(nil, tc.key)
suite.Require().Equal(tc.expValue, value, tc.name)
}
}
func (suite *StateDBTestSuite) TestStateObject_AddBalance() {
testCase := []struct {
name string
amount *big.Int
expBalance *big.Int
}{
{"zero amount", big.NewInt(0), big.NewInt(0)},
{"positive amount", big.NewInt(10), big.NewInt(10)},
{"negative amount", big.NewInt(-1), big.NewInt(9)},
}
for _, tc := range testCase {
suite.stateObject.AddBalance(tc.amount)
suite.Require().Equal(tc.expBalance, suite.stateObject.Balance(), tc.name)
}
}
func (suite *StateDBTestSuite) TestStateObject_SubBalance() {
testCase := []struct {
name string
amount *big.Int
expBalance *big.Int
}{
{"zero amount", big.NewInt(0), big.NewInt(0)},
{"negative amount", big.NewInt(-10), big.NewInt(10)},
{"positive amount", big.NewInt(1), big.NewInt(9)},
}
for _, tc := range testCase {
suite.stateObject.SubBalance(tc.amount)
suite.Require().Equal(tc.expBalance, suite.stateObject.Balance(), tc.name)
}
}
func (suite *StateDBTestSuite) TestStateObject_Code() {
testCase := []struct {
name string
expCode []byte
malleate func()
}{
{
"cached code",
[]byte("code"),
func() {
suite.stateObject.SetCode(ethcmn.BytesToHash([]byte("code_hash")), []byte("code"))
},
},
{
"empty code hash",
nil,
func() {
suite.stateObject.SetCode(ethcmn.Hash{}, nil)
},
},
{
"empty code",
nil,
func() {
suite.stateObject.SetCode(ethcmn.BytesToHash([]byte("code_hash")), nil)
},
},
}
for _, tc := range testCase {
tc.malleate()
code := suite.stateObject.Code(nil)
suite.Require().Equal(tc.expCode, code, tc.name)
}
}

View File

@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/suite"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
ethcmn "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
@ -14,6 +15,7 @@ import (
"github.com/cosmos/ethermint/app"
"github.com/cosmos/ethermint/crypto"
ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/x/evm/keeper"
"github.com/cosmos/ethermint/x/evm/types"
@ -23,10 +25,12 @@ import (
type StateDBTestSuite struct {
suite.Suite
ctx sdk.Context
querier sdk.Querier
app *app.EthermintApp
stateDB *types.CommitStateDB
ctx sdk.Context
querier sdk.Querier
app *app.EthermintApp
stateDB *types.CommitStateDB
address ethcmn.Address
stateObject types.StateObject
}
func TestStateDBTestSuite(t *testing.T) {
@ -40,6 +44,18 @@ func (suite *StateDBTestSuite) SetupTest() {
suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1})
suite.querier = keeper.NewQuerier(suite.app.EvmKeeper)
suite.stateDB = suite.app.EvmKeeper.CommitStateDB.WithContext(suite.ctx)
privkey, err := crypto.GenerateKey()
suite.Require().NoError(err)
suite.address = ethcmn.BytesToAddress(privkey.PubKey().Address().Bytes())
acc := &ethermint.EthAccount{
BaseAccount: auth.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0),
CodeHash: ethcrypto.Keccak256(nil),
}
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.stateObject = suite.stateDB.GetOrNewStateObject(suite.address)
}
func (suite *StateDBTestSuite) TestBloomFilter() {
@ -308,3 +324,113 @@ func (suite *StateDBTestSuite) TestSuiteDBSuicide() {
suite.Require().NoError(err)
suite.Require().False(suite.stateDB.Exist(addr))
}
func (suite *StateDBTestSuite) TestCommitStateDB_Commit() {
testCase := []struct {
name string
malleate func()
deleteObjs bool
expPass bool
}{
{
"commit suicided",
func() {
ok := suite.stateDB.Suicide(suite.address)
suite.Require().True(ok)
},
true, true,
},
{
"commit with dirty value",
func() {
suite.stateDB.SetCode(suite.address, []byte("code"))
},
false, true,
},
{
"faled to update state object",
func() {
suite.stateDB.SubBalance(suite.address, big.NewInt(10))
},
false, false,
},
}
for _, tc := range testCase {
tc.malleate()
hash, err := suite.stateDB.Commit(tc.deleteObjs)
suite.Require().Equal(ethcmn.Hash{}, hash)
if !tc.expPass {
suite.Require().Error(err, tc.name)
continue
}
suite.Require().NoError(err, tc.name)
acc := suite.app.AccountKeeper.GetAccount(suite.ctx, sdk.AccAddress(suite.address.Bytes()))
if tc.deleteObjs {
suite.Require().Nil(acc, tc.name)
continue
}
suite.Require().NotNil(acc, tc.name)
ethAcc, ok := acc.(*ethermint.EthAccount)
suite.Require().True(ok)
suite.Require().Equal(ethcrypto.Keccak256([]byte("code")), ethAcc.CodeHash)
}
}
func (suite *StateDBTestSuite) TestCommitStateDB_Finalize() {
testCase := []struct {
name string
malleate func()
deleteObjs bool
expPass bool
}{
{
"finalize suicided",
func() {
ok := suite.stateDB.Suicide(suite.address)
suite.Require().True(ok)
},
true, true,
},
{
"finalize, not suicided",
func() {
suite.stateDB.AddBalance(suite.address, big.NewInt(5))
},
false, true,
},
{
"faled to update state object",
func() {
suite.stateDB.SubBalance(suite.address, big.NewInt(10))
},
false, false,
},
}
for _, tc := range testCase {
tc.malleate()
err := suite.stateDB.Finalise(tc.deleteObjs)
if !tc.expPass {
suite.Require().Error(err, tc.name)
continue
}
suite.Require().NoError(err, tc.name)
acc := suite.app.AccountKeeper.GetAccount(suite.ctx, sdk.AccAddress(suite.address.Bytes()))
if tc.deleteObjs {
suite.Require().Nil(acc, tc.name)
continue
}
suite.Require().NotNil(acc, tc.name)
}
}