From c523b4af70089f642d27e5a96457d01007cd7d40 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Mon, 31 Aug 2020 09:25:47 +0200 Subject: [PATCH] Add mock EthClient for testing --- README.md | 2 +- coordinator/coordinator.go | 2 +- eth/client_test.go | 14 +++++++ eth/interface.go | 18 +++++++++ test/ethclient.go | 79 ++++++++++++++++++++++++++++++++++++++ test/ethclient_test.go | 46 ++++++++++++++++++++++ 6 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 eth/client_test.go create mode 100644 eth/interface.go create mode 100644 test/ethclient.go create mode 100644 test/ethclient_test.go diff --git a/README.md b/README.md index 146f60d..c380a60 100644 --- a/README.md +++ b/README.md @@ -17,5 +17,5 @@ POSTGRES_PASS=yourpasswordhere go test ./... - Install [golangci-lint](https://golangci-lint.run) - Once installed, to check the lints ``` -golangci-lint run --timeout=5m -E whitespace -E gosec -E gci -E misspell -E gomnd --max-same-issues 0 +golangci-lint run --timeout=5m -E whitespace -E gosec -E gci -E misspell -E gomnd -E gofmt -E goimports -E golint --exclude-use-default=false --max-same-issues 0 ``` diff --git a/coordinator/coordinator.go b/coordinator/coordinator.go index 12a86cd..84ecf3b 100644 --- a/coordinator/coordinator.go +++ b/coordinator/coordinator.go @@ -40,7 +40,7 @@ type Coordinator struct { txsel *txselector.TxSelector batchBuilder *batchbuilder.BatchBuilder - ethClient *eth.Client + ethClient eth.ClientInterface ethTxStore kvdb.Storage } diff --git a/eth/client_test.go b/eth/client_test.go new file mode 100644 index 0000000..db71eca --- /dev/null +++ b/eth/client_test.go @@ -0,0 +1,14 @@ +package eth + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestClientInterface(t *testing.T) { + var c ClientInterface + client := NewClient(nil, nil, nil, nil) + c = client + require.NotNil(t, c) +} diff --git a/eth/interface.go b/eth/interface.go new file mode 100644 index 0000000..a53b9ff --- /dev/null +++ b/eth/interface.go @@ -0,0 +1,18 @@ +package eth + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/hermeznetwork/hermez-node/common" +) + +// ClientInterface is the eth Client interface used by hermez-node modules to +// interact with Ethereum Blockchain and smart contracts. +type ClientInterface interface { + CurrentBlock() (*big.Int, error) + HeaderByNumber(context.Context, *big.Int) (*types.Header, error) + BlockByNumber(context.Context, *big.Int) (*common.Block, error) + ForgeCall(*common.CallDataForge) ([]byte, error) +} diff --git a/test/ethclient.go b/test/ethclient.go new file mode 100644 index 0000000..82fde10 --- /dev/null +++ b/test/ethclient.go @@ -0,0 +1,79 @@ +package test + +import ( + "context" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/hermeznetwork/hermez-node/common" + "github.com/hermeznetwork/hermez-node/log" +) + +// Client implements the eth.IClient interface, allowing to manipulate the +// values for testing, working with deterministic results. +type Client struct { + log bool + blockNum *big.Int +} + +// NewTestEthClient returns a new test Client that implements the eth.IClient +// interface, at the given initialBlockNumber. +func NewTestEthClient(l bool, initialBlockNumber int64) *Client { + return &Client{ + log: l, + blockNum: big.NewInt(initialBlockNumber), + } +} + +// Advance moves one block forward +func (c *Client) Advance() { + c.blockNum = c.blockNum.Add(c.blockNum, big.NewInt(1)) + if c.log { + log.Debugf("TestEthClient blockNum advanced: %d", c.blockNum) + } +} + +// SetBlockNum sets the Client.blockNum to the given blockNum +func (c *Client) SetBlockNum(blockNum *big.Int) { + c.blockNum = blockNum + if c.log { + log.Debugf("TestEthClient blockNum set to: %d", c.blockNum) + } +} + +// CurrentBlock returns the current blockNum +func (c *Client) CurrentBlock() (*big.Int, error) { + return c.blockNum, nil +} + +func newHeader(number *big.Int) *types.Header { + return &types.Header{ + Number: number, + Time: uint64(number.Int64()), + } +} + +// HeaderByNumber returns the *types.Header for the given block number in a +// deterministic way. +func (c *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + return newHeader(number), nil +} + +// BlockByNumber returns the *common.Block for the given block number in a +// deterministic way. +func (c *Client) BlockByNumber(ctx context.Context, number *big.Int) (*common.Block, error) { + header := newHeader(number) + + return &common.Block{ + EthBlockNum: uint64(number.Int64()), + Timestamp: time.Unix(number.Int64(), 0), + Hash: header.Hash(), + }, nil +} + +// ForgeCall send the *common.CallDataForge to the Forge method of the mock +// smart contract +func (c *Client) ForgeCall(*common.CallDataForge) ([]byte, error) { + return nil, nil +} diff --git a/test/ethclient_test.go b/test/ethclient_test.go new file mode 100644 index 0000000..a76e40b --- /dev/null +++ b/test/ethclient_test.go @@ -0,0 +1,46 @@ +package test + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/hermeznetwork/hermez-node/eth" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestClientInterface(t *testing.T) { + var c eth.ClientInterface + client := NewTestEthClient(true, 1000) + c = client + require.NotNil(t, c) +} + +func TestEthClient(t *testing.T) { + c := NewTestEthClient(true, 1000) + + block, err := c.BlockByNumber(context.TODO(), big.NewInt(3)) + assert.Nil(t, err) + assert.Equal(t, uint64(3), block.EthBlockNum) + assert.Equal(t, time.Unix(3, 0), block.Timestamp) + assert.Equal(t, "0x6b0ab5a7a0ebf5f05cef3b49bc7a9739de06469a4e05557d802ee828fdf5187e", block.Hash.Hex()) + + header, err := c.HeaderByNumber(context.TODO(), big.NewInt(4)) + assert.Nil(t, err) + assert.Equal(t, big.NewInt(4), header.Number) + assert.Equal(t, uint64(4), header.Time) + assert.Equal(t, "0x66cdb12322040a5a345ad29cea66ca97c14d6142b53987010947c8c008e26913", header.Hash().Hex()) + + assert.Equal(t, big.NewInt(1000), c.blockNum) + c.Advance() + assert.Equal(t, big.NewInt(1001), c.blockNum) + c.Advance() + assert.Equal(t, big.NewInt(1002), c.blockNum) + + c.SetBlockNum(big.NewInt(5000)) + assert.Equal(t, big.NewInt(5000), c.blockNum) + c.Advance() + assert.Equal(t, big.NewInt(5001), c.blockNum) +}