From 3508efc3afd7cd967f55c73b0892df27c3343e56 Mon Sep 17 00:00:00 2001 From: Deshi Xiao Date: Wed, 9 Jan 2019 20:35:10 +0800 Subject: [PATCH] fix #18254, Need to throw error when methods are called at future blocks -[x] add unit test for StorageAt rpc call -[x] Return error message on future block -[x] add TransactionCount rpc call unit testing Signed-off-by: Deshi Xiao --- eth/api_backend.go | 6 +- ethclient/ethclient_test.go | 178 +++++++++++++++++++++++++++++++++++- 2 files changed, 182 insertions(+), 2 deletions(-) diff --git a/eth/api_backend.go b/eth/api_backend.go index a48815e0db..61ca085bf4 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -18,6 +18,7 @@ package eth import ( "context" + "errors" "math/big" "github.com/ethereum/go-ethereum/accounts" @@ -94,9 +95,12 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc. } // Otherwise resolve the block number and return its state header, err := b.HeaderByNumber(ctx, blockNr) - if header == nil || err != nil { + if err != nil { return nil, nil, err } + if header == nil { + return nil, nil, errors.New("header not found at future block") + } stateDb, err := b.eth.BlockChain().StateAt(header.Root) return stateDb, header, err } diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 3e8bf974c2..5e8edde631 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -17,13 +17,16 @@ package ethclient import ( + "context" "fmt" "math/big" "reflect" "testing" + "time" - "github.com/ethereum/go-ethereum" + ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rpc" ) // Verify that Client implements the ethereum interfaces. @@ -150,3 +153,176 @@ func TestToFilterArg(t *testing.T) { }) } } + +func TestNewClient(t *testing.T) { + type args struct { + c *rpc.Client + } + tests := []struct { + name string + args args + want *Client + }{ + { + "new Client", + args{}, + &Client{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewClient(tt.args.c); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewClient() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestClient_StorageAt(t *testing.T) { + ctx := context.Background() + ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) + defer cancel() + + type fields struct { + c *rpc.Client + } + type args struct { + ctx context.Context + account common.Address + key common.Hash + blockNumber *big.Int + } + tests := []struct { + name string + fields fields + args args + want []byte + wantErr bool + }{ + { + "call StorageAt at future block", + fields{ + c: &rpc.Client{}, + }, + args{ + ctx: ctx, + account: common.HexToAddress("0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2"), + key: common.HexToHash("0x0"), + blockNumber: big.NewInt(1000000000), + }, + []byte(nil), + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ec := &Client{ + c: tt.fields.c, + } + got, err := ec.StorageAt(tt.args.ctx, tt.args.account, tt.args.key, tt.args.blockNumber) + if (err != nil) != tt.wantErr { + t.Errorf("Client.StorageAt() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Client.StorageAt() = %#v, want %#v", got, tt.want) + } + }) + } +} + +func TestClient_TransactionCount(t *testing.T) { + ctx := context.Background() + ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) + defer cancel() + + type fields struct { + c *rpc.Client + } + type args struct { + ctx context.Context + blockHash common.Hash + } + tests := []struct { + name string + fields fields + args args + want uint + wantErr bool + }{ + { + "call TransactionCount at future block", + fields{ + c: &rpc.Client{}, + }, + args{ + ctx: ctx, + blockHash: common.HexToHash("0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"), + }, + 0, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ec := &Client{ + c: tt.fields.c, + } + got, err := ec.TransactionCount(tt.args.ctx, tt.args.blockHash) + if (err != nil) != tt.wantErr { + t.Errorf("Client.TransactionCount() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Client.TransactionCount() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestClient_PendingTransactionCount(t *testing.T) { + ctx := context.Background() + ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) + defer cancel() + + type fields struct { + c *rpc.Client + } + type args struct { + ctx context.Context + } + tests := []struct { + name string + fields fields + args args + want uint + wantErr bool + }{ + { + "call TransactionCount at pending block", + fields{ + c: &rpc.Client{}, + }, + args{ + ctx: ctx, + }, + 0, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ec := &Client{ + c: tt.fields.c, + } + got, err := ec.PendingTransactionCount(tt.args.ctx) + if (err != nil) != tt.wantErr { + t.Errorf("Client.PendingTransactionCount() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Client.PendingTransactionCount() = %v, want %v", got, tt.want) + } + }) + } +}