Unverified Commit 5f70f9fd authored by Martin Holst Swende's avatar Martin Holst Swende Committed by GitHub

eth/tracers: simplify test framework (#25973)

Co-authored-by: 's avatarSina Mahmoodi <itz.s1na@gmail.com>
parent a404195c
......@@ -48,17 +48,18 @@ type callContext struct {
// callTrace is the result of a callTracer run.
type callTrace struct {
Type string `json:"type"`
From common.Address `json:"from"`
To common.Address `json:"to"`
Gas *hexutil.Uint64 `json:"gas"`
GasUsed *hexutil.Uint64 `json:"gasUsed"`
To common.Address `json:"to,omitempty"`
Input hexutil.Bytes `json:"input"`
Output hexutil.Bytes `json:"output"`
Gas *hexutil.Uint64 `json:"gas,omitempty"`
GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"`
Value *hexutil.Big `json:"value,omitempty"`
Output hexutil.Bytes `json:"output,omitempty"`
Error string `json:"error,omitempty"`
Revertal string `json:"revertReason,omitempty"`
Calls []callTrace `json:"calls,omitempty"`
Value *hexutil.Big `json:"value,omitempty"`
// Gencodec adds overridden fields at the end
Type string `json:"type"`
}
// callTracerTest defines a single test to check the call tracer against.
......@@ -144,17 +145,21 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil {
t.Fatalf("failed to retrieve trace result: %v", err)
}
ret := new(callTrace)
if err := json.Unmarshal(res, ret); err != nil {
t.Fatalf("failed to unmarshal trace result: %v", err)
// The legacy javascript calltracer marshals json in js, which
// is not deterministic (as opposed to the golang json encoder).
if strings.HasSuffix(dirPath, "_legacy") {
// This is a tweak to make it deterministic. Can be removed when
// we remove the legacy tracer.
var x callTrace
json.Unmarshal(res, &x)
res, _ = json.Marshal(x)
}
if !jsonEqual(ret, test.Result, new(callTrace), new(callTrace)) {
// uncomment this for easier debugging
//have, _ := json.MarshalIndent(ret, "", " ")
//want, _ := json.MarshalIndent(test.Result, "", " ")
//t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want))
t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, test.Result)
want, err := json.Marshal(test.Result)
if err != nil {
t.Fatalf("failed to marshal test: %v", err)
}
if string(want) != string(res) {
t.Fatalf("trace mismatch\n have: %v\n want: %v\n", string(res), string(want))
}
})
}
......@@ -298,14 +303,8 @@ func TestZeroValueToNotExitCall(t *testing.T) {
if err != nil {
t.Fatalf("failed to retrieve trace result: %v", err)
}
have := new(callTrace)
if err := json.Unmarshal(res, have); err != nil {
t.Fatalf("failed to unmarshal trace result: %v", err)
}
wantStr := `{"type":"CALL","from":"0x682a80a6f560eec50d54e63cbeda1c324c5f8d1b","to":"0x00000000000000000000000000000000deadbeef","value":"0x0","gas":"0x7148","gasUsed":"0x2d0","input":"0x","output":"0x","calls":[{"type":"CALL","from":"0x00000000000000000000000000000000deadbeef","to":"0x00000000000000000000000000000000000000ff","value":"0x0","gas":"0x6cbf","gasUsed":"0x0","input":"0x","output":"0x"}]}`
want := new(callTrace)
json.Unmarshal([]byte(wantStr), want)
if !jsonEqual(have, want, new(callTrace), new(callTrace)) {
t.Error("have != want")
wantStr := `{"from":"0x682a80a6f560eec50d54e63cbeda1c324c5f8d1b","gas":"0x7148","gasUsed":"0x2d0","to":"0x00000000000000000000000000000000deadbeef","input":"0x","calls":[{"from":"0x00000000000000000000000000000000deadbeef","gas":"0x6cbf","gasUsed":"0x0","to":"0x00000000000000000000000000000000000000ff","input":"0x","value":"0x0","type":"CALL"}],"value":"0x0","type":"CALL"}`
if string(res) != wantStr {
t.Fatalf("trace mismatch\n have: %v\n want: %v\n", string(res), wantStr)
}
}
......@@ -35,19 +35,16 @@ import (
// prestateTrace is the result of a prestateTrace run.
type prestateTrace = map[common.Address]*account
type account struct {
Balance string `json:"balance,omitempty"`
Nonce uint64 `json:"nonce,omitempty"`
Code string `json:"code,omitempty"`
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
}
type prePostStateTrace struct {
Pre prestateTrace `json:"pre"`
Post prestateTrace `json:"post"`
Balance string `json:"balance"`
Code string `json:"code"`
Nonce uint64 `json:"nonce"`
Storage map[common.Hash]common.Hash `json:"storage"`
}
// prestateTraceTest defines a single test to check the stateDiff tracer against.
type prestateTraceTest struct {
// testcase defines a single test to check the stateDiff tracer against.
type testcase struct {
Genesis *core.Genesis `json:"genesis"`
Context *callContext `json:"context"`
Input string `json:"input"`
......@@ -55,15 +52,19 @@ type prestateTraceTest struct {
Result interface{} `json:"result"`
}
func TestPrestateTracerLegacy(t *testing.T) {
testPrestateDiffTracer("prestateTracerLegacy", "prestate_tracer_legacy", t)
}
func TestPrestateTracer(t *testing.T) {
testPrestateDiffTracer("prestateTracer", "prestate_tracer", t, func() interface{} { return new(prestateTrace) })
testPrestateDiffTracer("prestateTracer", "prestate_tracer", t)
}
func TestPrestateWithDiffModeTracer(t *testing.T) {
testPrestateDiffTracer("prestateTracer", "prestate_tracer_with_diff_mode", t, func() interface{} { return new(prePostStateTrace) })
testPrestateDiffTracer("prestateTracer", "prestate_tracer_with_diff_mode", t)
}
func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T, typeBuilder func() interface{}) {
func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
files, err := os.ReadDir(filepath.Join("testdata", dirPath))
if err != nil {
t.Fatalf("failed to retrieve tracer test suite: %v", err)
......@@ -77,7 +78,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T, typ
t.Parallel()
var (
test = new(prestateTraceTest)
test = new(testcase)
tx = new(types.Transaction)
)
// Call tracer test found, read if from disk
......@@ -127,17 +128,21 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T, typ
if err != nil {
t.Fatalf("failed to retrieve trace result: %v", err)
}
ret := typeBuilder()
if err := json.Unmarshal(res, ret); err != nil {
t.Fatalf("failed to unmarshal trace result: %v", err)
// The legacy javascript calltracer marshals json in js, which
// is not deterministic (as opposed to the golang json encoder).
if strings.HasSuffix(dirPath, "_legacy") {
// This is a tweak to make it deterministic. Can be removed when
// we remove the legacy tracer.
var x prestateTrace
json.Unmarshal(res, &x)
res, _ = json.Marshal(x)
}
if !jsonEqual(ret, test.Result, typeBuilder(), typeBuilder()) {
// uncomment this for easier debugging
// have, _ := json.MarshalIndent(ret, "", " ")
// want, _ := json.MarshalIndent(test.Result, "", " ")
// t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want))
t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, test.Result)
want, err := json.Marshal(test.Result)
if err != nil {
t.Fatalf("failed to marshal test: %v", err)
}
if string(want) != string(res) {
t.Fatalf("trace mismatch\n have: %v\n want: %v\n", string(res), string(want))
}
})
}
......
......@@ -77,8 +77,7 @@
"nonce": 29072
},
"0x1585936b53834b021f68cc13eeefdec2efc8e724": {
"balance": "0x0",
"nonce": 0
"balance": "0x0"
}
}
}
package tracetest
import (
"encoding/json"
"reflect"
"strings"
"unicode"
......@@ -64,22 +62,6 @@ var makeTest = function(tx, rewind) {
}
*/
// jsonEqual is similar to reflect.DeepEqual, but does a 'bounce' via json prior to
// comparison
func jsonEqual(xi, yi, xt, yt interface{}) bool {
if xj, err := json.Marshal(xi); err == nil {
json.Unmarshal(xj, xt)
} else {
return false
}
if yj, err := json.Marshal(yi); err == nil {
json.Unmarshal(yj, yt)
} else {
return false
}
return reflect.DeepEqual(xt, yt)
}
// camel converts a snake cased input string into a camel cased output.
func camel(str string) string {
pieces := strings.Split(str, "_")
......
......@@ -204,7 +204,6 @@
gasUsed: '0x' + bigInt(ctx.gasUsed).toString(16),
input: toHex(ctx.input),
output: toHex(ctx.output),
time: ctx.time,
};
if (this.callstack[0].calls !== undefined) {
result.calls = this.callstack[0].calls;
......
......@@ -16,14 +16,14 @@ var _ = (*accountMarshaling)(nil)
func (a account) MarshalJSON() ([]byte, error) {
type account struct {
Balance *hexutil.Big `json:"balance,omitempty"`
Nonce uint64 `json:"nonce,omitempty"`
Code hexutil.Bytes `json:"code,omitempty"`
Nonce uint64 `json:"nonce,omitempty"`
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
}
var enc account
enc.Balance = (*hexutil.Big)(a.Balance)
enc.Nonce = a.Nonce
enc.Code = a.Code
enc.Nonce = a.Nonce
enc.Storage = a.Storage
return json.Marshal(&enc)
}
......@@ -31,10 +31,10 @@ func (a account) MarshalJSON() ([]byte, error) {
// UnmarshalJSON unmarshals from JSON.
func (a *account) UnmarshalJSON(input []byte) error {
type account struct {
Balance *hexutil.Big `json:"balance"`
Nonce *uint64 `json:"nonce"`
Code *hexutil.Bytes `json:"code"`
Storage map[common.Hash]common.Hash `json:"storage"`
Balance *hexutil.Big `json:"balance,omitempty"`
Code *hexutil.Bytes `json:"code,omitempty"`
Nonce *uint64 `json:"nonce,omitempty"`
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
}
var dec account
if err := json.Unmarshal(input, &dec); err != nil {
......@@ -43,12 +43,12 @@ func (a *account) UnmarshalJSON(input []byte) error {
if dec.Balance != nil {
a.Balance = (*big.Int)(dec.Balance)
}
if dec.Nonce != nil {
a.Nonce = *dec.Nonce
}
if dec.Code != nil {
a.Code = *dec.Code
}
if dec.Nonce != nil {
a.Nonce = *dec.Nonce
}
if dec.Storage != nil {
a.Storage = dec.Storage
}
......
......@@ -40,8 +40,8 @@ type state = map[common.Address]*account
type account struct {
Balance *big.Int `json:"balance,omitempty"`
Nonce uint64 `json:"nonce,omitempty"`
Code []byte `json:"code,omitempty"`
Nonce uint64 `json:"nonce,omitempty"`
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
}
......@@ -253,9 +253,9 @@ func (t *prestateTracer) GetResult() (json.RawMessage, error) {
var err error
if t.config.DiffMode {
res, err = json.Marshal(struct {
Pre state `json:"pre"`
Post state `json:"post"`
}{t.pre, t.post})
Pre state `json:"pre"`
}{t.post, t.pre})
} else {
res, err = json.Marshal(t.pre)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment