Added tests to ensure we covers balance and gas change correctly

This commit is contained in:
Matthieu Vachon 2025-02-21 11:31:32 -05:00
parent 66d5c7ee57
commit 1b285b8c81
2 changed files with 55 additions and 1 deletions

View file

@ -2068,7 +2068,7 @@ var gasChangeReasonToPb = map[tracing.GasChangeReason]pbeth.GasChange_Reason{
tracing.GasChangeWitnessContractCollisionCheck: pbeth.GasChange_REASON_WITNESS_CONTRACT_COLLISION_CHECK, tracing.GasChangeWitnessContractCollisionCheck: pbeth.GasChange_REASON_WITNESS_CONTRACT_COLLISION_CHECK,
tracing.GasChangeTxDataFloor: pbeth.GasChange_REASON_TX_DATA_FLOOR, tracing.GasChangeTxDataFloor: pbeth.GasChange_REASON_TX_DATA_FLOOR,
// Ignored, we track them manually, newGasChange ensure that we panic if we see Unknown // Ignored, we track them manually, [newGasChange] ensure that we panic if we see Unknown
tracing.GasChangeCallOpCode: pbeth.GasChange_REASON_UNKNOWN, tracing.GasChangeCallOpCode: pbeth.GasChange_REASON_UNKNOWN,
} }

View file

@ -3,9 +3,11 @@ package tracers
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"math"
"math/big" "math/big"
"os" "os"
"reflect" "reflect"
"regexp"
"slices" "slices"
"testing" "testing"
@ -188,6 +190,58 @@ func Test_FirehoseAndGethHeaderFieldMatches(t *testing.T) {
} }
} }
var endsWithUnknownConstant = regexp.MustCompile(`.*\(\d+\)$`)
func TestFirehose_BalanceChangeAllMappedCorrectly(t *testing.T) {
for i := 0; i <= math.MaxUint8; i++ {
tracingReason := tracing.BalanceChangeReason(i)
if tracingReason == tracing.BalanceChangeUnspecified || tracingReason == tracing.BalanceChangeRevert {
// Should never happen in Firehose tracer, only if tracer is wrapped with [tracing.WrapWithJournal]
continue
}
// Here, we leverage the fact that the `tracing.BalanceChangeReason` Stringer will render the String
// as `<EnumName>(<indexValue>)` if the index is not mapped to a constant in the enum. If this happens,
// we know it's not a defined constant in the Geth tracing package.
//
// Otherwise, it's defined and we should have some mapping for it in the `balanceChangeReasonFromChain` function.
//
// There is a loophole of this technique and it's that if the code generator defining the enum Stringer is
// not run, we will think it's an undefined constant and will miss it.
if !endsWithUnknownConstant.MatchString(tracingReason.String()) {
require.NotPanics(t, func() {
balanceChangeReasonFromChain(tracingReason)
}, "BalanceChangeReason panicked for value %v", tracingReason)
}
}
}
func TestFirehose_GasChangeAllMappedCorrectly(t *testing.T) {
for i := 0; i <= math.MaxUint8; i++ {
tracingReason := tracing.GasChangeReason(i)
// Those are ignored and never mapped
if tracingReason == tracing.GasChangeUnspecified || tracingReason == tracing.GasChangeCallOpCode || tracingReason == tracing.GasChangeIgnored {
continue
}
// Here, we leverage the fact that the `tracing.GasChangeReason` Stringer will render the String
// as `<EnumName>(<indexValue>)` if the index is not mapped to a constant in the enum. If this happens,
// we know it's not a defined constant in the Geth tracing package.
//
// Otherwise, it's defined and we should have some mapping for it in the `gasChangeReasonFromChain` function.
//
// There is a loophole of this technique and it's that if the code generator defining the enum Stringer is
// not run, we will think it's an undefined constant and will miss it.
if !endsWithUnknownConstant.MatchString(tracingReason.String()) {
require.NotPanics(t, func() {
gasChangeReasonFromChain(tracingReason)
}, "GasChangeReason panicked for value %v", tracingReason)
}
}
}
func fillAllFieldsWithNonEmptyValues(t *testing.T, structValue reflect.Value, fields []reflect.StructField) { func fillAllFieldsWithNonEmptyValues(t *testing.T, structValue reflect.Value, fields []reflect.StructField) {
t.Helper() t.Helper()