unit tests on new functions

This commit is contained in:
Lucca Martins 2025-01-27 04:37:37 -03:00
parent 7fee5576b2
commit 8255ce1e1f
No known key found for this signature in database
GPG key ID: DC3D7F76BDAE23BF
6 changed files with 338 additions and 3 deletions

View file

@ -1,5 +1,6 @@
package abi
//go:generate mockgen -destination=./abi_mock.go -package=api . ABI
type ABI interface {
Pack(name string, args ...interface{}) ([]byte, error)
UnpackIntoInterface(v interface{}, name string, data []byte) error

View file

@ -0,0 +1,68 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/ethereum/go-ethereum/consensus/bor/abi (interfaces: ABI)
// Package abi is a generated GoMock package.
package abi
import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
)
// MockABI is a mock of ABI interface.
type MockABI struct {
ctrl *gomock.Controller
recorder *MockABIMockRecorder
}
// MockABIMockRecorder is the mock recorder for MockABI.
type MockABIMockRecorder struct {
mock *MockABI
}
// NewMockABI creates a new mock instance.
func NewMockABI(ctrl *gomock.Controller) *MockABI {
mock := &MockABI{ctrl: ctrl}
mock.recorder = &MockABIMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockABI) EXPECT() *MockABIMockRecorder {
return m.recorder
}
// Pack mocks base method.
func (m *MockABI) Pack(arg0 string, arg1 ...interface{}) ([]byte, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Pack", varargs...)
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Pack indicates an expected call of Pack.
func (mr *MockABIMockRecorder) Pack(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Pack", reflect.TypeOf((*MockABI)(nil).Pack), varargs...)
}
// UnpackIntoInterface mocks base method.
func (m *MockABI) UnpackIntoInterface(arg0 interface{}, arg1 string, arg2 []byte) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UnpackIntoInterface", arg0, arg1, arg2)
ret0, _ := ret[0].(error)
return ret0
}
// UnpackIntoInterface indicates an expected call of UnpackIntoInterface.
func (mr *MockABIMockRecorder) UnpackIntoInterface(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnpackIntoInterface", reflect.TypeOf((*MockABI)(nil).UnpackIntoInterface), arg0, arg1, arg2)
}

View file

@ -138,7 +138,7 @@ func (c *ChainSpanner) tryGetBorValidatorsWithId(ctx context.Context, blockNrOrH
valz := make([]*valset.Validator, producersCount)
for i := 0; i < producersCount; i++ {
p, err := c.getProducersBySpanAndIndexMethod(ctx, blockNrOrHash, blockNumber, toAddress, gas, spanNumber, i)
p, err := c.getProducersBySpanAndIndexMethod(ctx, blockNrOrHash, toAddress, gas, spanNumber, i)
// if fails, return validators without id
if err != nil {
return borValidatorsWithoutId, nil
@ -180,7 +180,7 @@ func (c *ChainSpanner) getSpanByBlock(ctx context.Context, blockNrOrHash rpc.Blo
return spanNumber, nil
}
func (c *ChainSpanner) getProducersBySpanAndIndexMethod(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, blockNumber uint64, toAddress common.Address, gas hexutil.Uint64, spanNumber *big.Int, index int) (*contractValidator, error) {
func (c *ChainSpanner) getProducersBySpanAndIndexMethod(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, toAddress common.Address, gas hexutil.Uint64, spanNumber *big.Int, index int) (*contractValidator, error) {
const getProducersBySpanAndIndexMethod = "producers"
producerData, err := c.validatorSet.Pack(getProducersBySpanAndIndexMethod, spanNumber, big.NewInt(int64(index)))
if err != nil {

View file

@ -0,0 +1,206 @@
package span
import (
"context"
"fmt"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/bor/abi"
"github.com/ethereum/go-ethereum/consensus/bor/api"
"github.com/ethereum/go-ethereum/consensus/bor/valset"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
func TestGetCurrentValidatorsByBlockNrOrHash(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
chainConfig := &params.ChainConfig{}
validatorContractAddress := common.HexToAddress("0x1234567890123456789012345678901234567890")
testCases := []struct {
name string
blockNumber uint64
mockEthAPIExpected func(*api.MockCaller)
mockAbiExpected func(*abi.MockABI)
expectedValidators []*valset.Validator
expectError bool
}{
{
name: "Successful retrieval of validators",
blockNumber: 1000,
mockEthAPIExpected: func(mockCaller *api.MockCaller) {
mockCaller.EXPECT().Call(
gomock.Any(),
gomock.Any(),
gomock.Any(),
gomock.Any(),
gomock.Any(),
).Return(common.FromHex("0x0000000000000000000000000000000000000000000000000000000000000000"), nil).AnyTimes()
},
mockAbiExpected: func(mockAbi *abi.MockABI) {
basicMocks(mockAbi)
callCount := 0
mockAbi.EXPECT().UnpackIntoInterface(
gomock.Any(),
gomock.Eq("producers"),
gomock.Any(),
).DoAndReturn(func(v interface{}, name string, data []byte) error {
defer func() { callCount++ }()
resp, _ := v.(*contractValidator)
if callCount == 0 {
*resp = contractValidator{
Id: big.NewInt(1),
Signer: common.HexToAddress("0x1111111111111111111111111111111111111111"),
Power: big.NewInt(10),
}
}
if callCount == 1 {
*resp = contractValidator{
Id: big.NewInt(2),
Signer: common.HexToAddress("0x2222222222222222222222222222222222222222"),
Power: big.NewInt(15),
}
}
return nil
}).AnyTimes()
},
expectedValidators: []*valset.Validator{
{
ID: 1,
Address: common.HexToAddress("0x1111111111111111111111111111111111111111"),
VotingPower: 10,
},
{
ID: 2,
Address: common.HexToAddress("0x2222222222222222222222222222222222222222"),
VotingPower: 15,
},
},
expectError: false,
},
{
name: "Successful retrieval of validators without id",
blockNumber: 1000,
mockEthAPIExpected: func(mockCaller *api.MockCaller) {
mockCaller.EXPECT().Call(
gomock.Any(),
gomock.Any(),
gomock.Any(),
gomock.Any(),
gomock.Any(),
).Return(common.FromHex("0x0000000000000000000000000000000000000000000000000000000000000000"), nil).AnyTimes()
},
mockAbiExpected: func(mockAbi *abi.MockABI) {
basicMocks(mockAbi)
mockAbi.EXPECT().UnpackIntoInterface(
gomock.Any(),
gomock.Eq("producers"),
gomock.Any(),
).DoAndReturn(func(v interface{}, name string, data []byte) error {
return fmt.Errorf("failed")
}).AnyTimes()
},
expectedValidators: []*valset.Validator{
{
ID: 0,
Address: common.HexToAddress("0x1111111111111111111111111111111111111111"),
VotingPower: 10,
},
{
ID: 0,
Address: common.HexToAddress("0x2222222222222222222222222222222222222222"),
VotingPower: 15,
},
},
expectError: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
mockEthAPI := api.NewMockCaller(ctrl)
mockValidatorSetABI := abi.NewMockABI(ctrl)
// Setup
chainSpanner := NewChainSpanner(
mockEthAPI,
mockValidatorSetABI,
chainConfig,
validatorContractAddress,
)
// Set up mock expectations
tc.mockEthAPIExpected(mockEthAPI)
tc.mockAbiExpected(mockValidatorSetABI)
blockNumber := rpc.BlockNumber(tc.blockNumber)
blockNrOrHash := rpc.BlockNumberOrHashWithNumber(blockNumber)
// Execute method
validators, err := chainSpanner.GetCurrentValidatorsByBlockNrOrHash(context.Background(), blockNrOrHash, tc.blockNumber)
// Assertions
if tc.expectError {
assert.Error(t, err)
assert.Nil(t, validators)
} else {
assert.NoError(t, err)
assert.Equal(t, tc.expectedValidators, validators)
}
})
}
}
func basicMocks(mockAbi *abi.MockABI) {
mockAbi.EXPECT().Pack(
gomock.Any(),
gomock.Any(),
).Return(common.FromHex("0x0000000000000000000000000000000000000000000000000000000000000000"), nil).AnyTimes()
mockAbi.EXPECT().UnpackIntoInterface(
gomock.Any(),
gomock.Eq("FIRST_END_BLOCK"),
gomock.Any(),
).DoAndReturn(func(v interface{}, name string, data []byte) error {
resp, _ := v.(**big.Int)
*resp = big.NewInt(999)
return nil
}).AnyTimes()
mockAbi.EXPECT().UnpackIntoInterface(
gomock.Any(),
gomock.Eq("getSpanByBlock"),
gomock.Any(),
).DoAndReturn(func(v interface{}, name string, data []byte) error {
resp, _ := v.(**big.Int)
*resp = big.NewInt(1)
return nil
}).AnyTimes()
mockAbi.EXPECT().UnpackIntoInterface(
gomock.Any(),
gomock.Eq("getBorValidators"),
gomock.Any(),
).DoAndReturn(func(v interface{}, name string, data []byte) error {
resp, _ := v.(*[]interface{})
ret0, _ := (*resp)[0].(*[]common.Address)
ret1, _ := (*resp)[1].(*[]*big.Int)
*ret0 = []common.Address{common.HexToAddress("0x1111111111111111111111111111111111111111"), common.HexToAddress("0x2222222222222222222222222222222222222222")}
*ret1 = []*big.Int{big.NewInt(10), big.NewInt(15)}
return nil
}).AnyTimes()
}

View file

@ -114,7 +114,7 @@ func (vals *ValidatorSet) IncrementProposerPriority(times int) {
// validator queried on ValidatorSet contract
func (vals *ValidatorSet) IncludeIds(valsWithId []*Validator) {
if vals.IsNilOrEmpty() {
panic("empty validator set")
log.Warn("Empty validator set")
}
addressToId := make(map[common.Address]uint64)

View file

@ -197,3 +197,63 @@ func TestUpdateWithChangeSet(t *testing.T) {
_, updatedTempVal := valSet.GetByAddress(tempVal.Address)
require.Equal(t, int64(250), updatedTempVal.VotingPower)
}
func TestValidatorSet_IncludeIds(t *testing.T) {
v1 := &Validator{
Address: common.HexToAddress("0x1111111111111111111111111111111111111111"),
VotingPower: 100,
ProposerPriority: 0,
ID: 0,
}
v2 := &Validator{
Address: common.HexToAddress("0x2222222222222222222222222222222222222222"),
VotingPower: 200,
ProposerPriority: 0,
ID: 0,
}
valSet := NewValidatorSet([]*Validator{v1, v2})
valsWithId := []*Validator{
{
Address: v1.Address,
ID: 10, // new ID for v1
VotingPower: 999,
ProposerPriority: 999,
},
{
Address: v2.Address,
ID: 20, // new ID for v2
VotingPower: 999,
ProposerPriority: 999,
},
{
Address: common.HexToAddress("0x3333333333333333333333333333333333333333"),
ID: 30,
VotingPower: 300,
},
}
valSet.IncludeIds(valsWithId)
assert.Equal(t, uint64(10), valSet.Validators[0].ID, "v1 ID should be updated to 10")
assert.Equal(t, uint64(20), valSet.Validators[1].ID, "v2 ID should be updated to 20")
assert.Equal(t, 2, len(valSet.Validators), "No extra validators should be added")
assert.Equal(t, int64(100), valSet.Validators[0].VotingPower)
assert.Equal(t, int64(200), valSet.Validators[1].VotingPower)
}
func TestValidatorSet_IncludeIds_EmptySet(t *testing.T) {
valSet := NewValidatorSet(nil) // empty set
valSet.IncludeIds([]*Validator{
{
Address: common.HexToAddress("0xabcdef"),
ID: 42,
},
})
assert.Equal(t, 0, valSet.Size(), "ValidatorSet remains empty")
}