mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 09:23:48 +00:00
chore(core/types): add Test_CopyHeader test
This commit is contained in:
parent
04a336aee8
commit
5e413e4ab7
1 changed files with 141 additions and 0 deletions
|
|
@ -22,6 +22,8 @@ import (
|
|||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
"unicode"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
|
|
@ -29,6 +31,8 @@ import (
|
|||
"github.com/ethereum/go-ethereum/internal/blocktest"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// from bcValidBlockTest.json, "SimpleTx"
|
||||
|
|
@ -318,3 +322,140 @@ func TestRlpDecodeParentHash(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyHeader(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("empty_header", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
empty := Header{}
|
||||
cpy := CopyHeader(&empty)
|
||||
|
||||
want := &Header{
|
||||
Difficulty: new(big.Int),
|
||||
Number: new(big.Int),
|
||||
}
|
||||
assert.Equal(t, want, cpy)
|
||||
})
|
||||
|
||||
t.Run("filled_header", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
h := Header{
|
||||
ParentHash: common.Hash{1},
|
||||
UncleHash: common.Hash{2},
|
||||
Coinbase: common.Address{3},
|
||||
Root: common.Hash{4},
|
||||
TxHash: common.Hash{5},
|
||||
ReceiptHash: common.Hash{6},
|
||||
Bloom: Bloom{7},
|
||||
Difficulty: big.NewInt(8),
|
||||
Number: big.NewInt(9),
|
||||
GasLimit: 10,
|
||||
GasUsed: 11,
|
||||
Time: 12,
|
||||
Extra: []byte{13},
|
||||
MixDigest: common.Hash{14},
|
||||
Nonce: BlockNonce{15},
|
||||
BaseFee: big.NewInt(16),
|
||||
WithdrawalsHash: &common.Hash{17},
|
||||
BlobGasUsed: ptrTo(uint64(18)),
|
||||
ExcessBlobGas: ptrTo(uint64(19)),
|
||||
ParentBeaconRoot: &common.Hash{20},
|
||||
RequestsHash: &common.Hash{21},
|
||||
}
|
||||
|
||||
allFieldsAreSet(t, h)
|
||||
|
||||
cpy := CopyHeader(&h)
|
||||
|
||||
want := &Header{
|
||||
ParentHash: common.Hash{1},
|
||||
UncleHash: common.Hash{2},
|
||||
Coinbase: common.Address{3},
|
||||
Root: common.Hash{4},
|
||||
TxHash: common.Hash{5},
|
||||
ReceiptHash: common.Hash{6},
|
||||
Bloom: Bloom{7},
|
||||
Difficulty: big.NewInt(8),
|
||||
Number: big.NewInt(9),
|
||||
GasLimit: 10,
|
||||
GasUsed: 11,
|
||||
Time: 12,
|
||||
Extra: []byte{13},
|
||||
MixDigest: common.Hash{14},
|
||||
Nonce: BlockNonce{15},
|
||||
BaseFee: big.NewInt(16),
|
||||
WithdrawalsHash: &common.Hash{17},
|
||||
BlobGasUsed: ptrTo(uint64(18)),
|
||||
ExcessBlobGas: ptrTo(uint64(19)),
|
||||
ParentBeaconRoot: &common.Hash{20},
|
||||
RequestsHash: &common.Hash{21},
|
||||
}
|
||||
assert.Equal(t, want, cpy)
|
||||
|
||||
// Mutate each non-value field to ensure they are not shared
|
||||
v := reflect.ValueOf(&h).Elem()
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Field(i)
|
||||
fieldName := v.Type().Field(i).Name
|
||||
if unicode.IsLower(rune(fieldName[0])) {
|
||||
field = reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem()
|
||||
}
|
||||
var originalField any
|
||||
switch field.Kind() {
|
||||
case reflect.Array, reflect.Uint64: // values
|
||||
case reflect.Slice:
|
||||
originalField = field.Interface()
|
||||
switch originalField.(type) {
|
||||
case []byte:
|
||||
field.Set(reflect.Append(field, reflect.ValueOf(byte(1))))
|
||||
default:
|
||||
t.Fatalf("unexpected slice type %T for %q", originalField, fieldName)
|
||||
}
|
||||
originalField = field.Interface()
|
||||
case reflect.Pointer:
|
||||
originalField = field.Interface()
|
||||
switch ptr := originalField.(type) {
|
||||
case *big.Int:
|
||||
ptr.Add(ptr, big.NewInt(1))
|
||||
case *uint64:
|
||||
*ptr++
|
||||
case *common.Hash:
|
||||
ptr[0]++
|
||||
default:
|
||||
t.Fatalf("unexpected pointer type %T for %q", ptr, fieldName)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("unexpected field kind %v for %q", field.Kind(), fieldName)
|
||||
}
|
||||
cpyField := reflect.ValueOf(*cpy).Field(i).Interface()
|
||||
assert.NotEqualf(t, originalField, cpyField, "field %q", fieldName)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func ptrTo[T any](x T) *T { return &x }
|
||||
|
||||
func allFieldsAreSet(t *testing.T, x any) {
|
||||
v := reflect.ValueOf(x)
|
||||
typ := v.Type()
|
||||
require.Equal(t, reflect.Struct, typ.Kind())
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Field(i)
|
||||
fieldName := typ.Field(i).Name
|
||||
fieldValue := field
|
||||
if unicode.IsLower(rune(fieldName[0])) { // unexported
|
||||
require.Falsef(t, field.IsNil(), "field %q is nil", fieldName)
|
||||
field = reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem()
|
||||
fieldValue = field
|
||||
}
|
||||
if field.Kind() == reflect.Pointer {
|
||||
require.NotNilf(t, field.Interface(), "field %q is nil", fieldName)
|
||||
fieldValue = field.Elem()
|
||||
}
|
||||
isSet := fieldValue.IsValid() && !fieldValue.IsZero()
|
||||
require.True(t, isSet, "field %q is not set", fieldName)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue