Skip to content

Commit

Permalink
eth/tracers: simplify tests + make table-driven
Browse files Browse the repository at this point in the history
  • Loading branch information
holiman committed Dec 21, 2020
1 parent f8173ab commit 87dffcf
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 105 deletions.
2 changes: 0 additions & 2 deletions eth/tracers/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,6 @@ func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost
// Initialize the context if it wasn't done yet
if !jst.inited {
jst.ctx["block"] = env.Context.BlockNumber.Uint64()

// Compute intrinsic gas
isHomestead := env.ChainConfig().IsHomestead(env.Context.BlockNumber)
isIstanbul := env.ChainConfig().IsIstanbul(env.Context.BlockNumber)
Expand All @@ -562,7 +561,6 @@ func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost
return err
}
jst.ctx["intrinsicGas"] = intrinsicGas

jst.inited = true
}
// If tracing was interrupted, set the error and stop
Expand Down
149 changes: 46 additions & 103 deletions eth/tracers/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package tracers

import (
"bytes"
"encoding/json"
"errors"
"math/big"
Expand Down Expand Up @@ -61,9 +60,9 @@ func testCtx() *vmContext {

func runTrace(tracer *Tracer, vmctx *vmContext) (json.RawMessage, error) {
env := vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
var(
var (
startGas uint64 = 10000
value = big.NewInt(0)
value = big.NewInt(0)
)
contract := vm.NewContract(account{}, account{}, value, startGas)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
Expand All @@ -77,87 +76,50 @@ func runTrace(tracer *Tracer, vmctx *vmContext) (json.RawMessage, error) {
return tracer.GetResult()
}

// TestRegressionPanicSlice tests that we don't panic on bad arguments to memory access
func TestRegressionPanicSlice(t *testing.T) {
vmctx := testCtx()
tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.memory.slice(-1,-2)); }, fault: function() {}, result: function() { return this.depths; }}", vmctx.txCtx)
if err != nil {
t.Fatal(err)
}
if _, err = runTrace(tracer, vmctx); err != nil {
t.Fatal(err)
}
}

// TestRegressionPanicSlice tests that we don't panic on bad arguments to stack peeks
func TestRegressionPanicPeek(t *testing.T) {
vmctx := testCtx()
tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.stack.peek(-1)); }, fault: function() {}, result: function() { return this.depths; }}", vmctx.txCtx)
if err != nil {
t.Fatal(err)
}
if _, err = runTrace(tracer, vmctx); err != nil {
t.Fatal(err)
}
}

// TestRegressionPanicSlice tests that we don't panic on bad arguments to memory getUint
func TestRegressionPanicGetUint(t *testing.T) {
vmctx := testCtx()
tracer, err := New("{ depths: [], step: function(log, db) { this.depths.push(log.memory.getUint(-64));}, fault: function() {}, result: function() { return this.depths; }}", vmctx.txCtx)
if err != nil {
t.Fatal(err)
}
if _, err = runTrace(tracer, vmctx); err != nil {
t.Fatal(err)
}
}

func TestTracing(t *testing.T) {
vmctx := testCtx()
tracer, err := New("{count: 0, step: function() { this.count += 1; }, fault: function() {}, result: function() { return this.count; }}", vmctx.txCtx)
if err != nil {
t.Fatal(err)
}

ret, err := runTrace(tracer, vmctx)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(ret, []byte("3")) {
t.Errorf("Expected return value to be 3, got %s", string(ret))
}
}

func TestStack(t *testing.T) {
vmctx := testCtx()
tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.stack.length()); }, fault: function() {}, result: function() { return this.depths; }}", vmctx.txCtx)
if err != nil {
t.Fatal(err)
}

ret, err := runTrace(tracer, vmctx)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(ret, []byte("[0,1,2]")) {
t.Errorf("Expected return value to be [0,1,2], got %s", string(ret))
}
}

func TestOpcodes(t *testing.T) {
vmctx := testCtx()
tracer, err := New("{opcodes: [], step: function(log) { this.opcodes.push(log.op.toString()); }, fault: function() {}, result: function() { return this.opcodes; }}", vmctx.txCtx)
if err != nil {
t.Fatal(err)
}

ret, err := runTrace(tracer, vmctx)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(ret, []byte("[\"PUSH1\",\"PUSH1\",\"STOP\"]")) {
t.Errorf("Expected return value to be [\"PUSH1\",\"PUSH1\",\"STOP\"], got %s", string(ret))
func TestTracer(t *testing.T) {
execTracer := func(code string) []byte {
t.Helper()
ctx := &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}}
tracer, err := New(code, ctx.txCtx)
if err != nil {
t.Fatal(err)
}
ret, err := runTrace(tracer, ctx)
if err != nil {
t.Fatal(err)
}
return ret
}
for i, tt := range []struct {
code string
want string
}{
{ // tests that we don't panic on bad arguments to memory access
code: "{depths: [], step: function(log) { this.depths.push(log.memory.slice(-1,-2)); }, fault: function() {}, result: function() { return this.depths; }}",
want: `[{},{},{}]`,
}, { // tests that we don't panic on bad arguments to stack peeks
code: "{depths: [], step: function(log) { this.depths.push(log.stack.peek(-1)); }, fault: function() {}, result: function() { return this.depths; }}",
want: `["0","0","0"]`,
}, { // tests that we don't panic on bad arguments to memory getUint
code: "{ depths: [], step: function(log, db) { this.depths.push(log.memory.getUint(-64));}, fault: function() {}, result: function() { return this.depths; }}",
want: `["0","0","0"]`,
}, { // tests some general counting
code: "{count: 0, step: function() { this.count += 1; }, fault: function() {}, result: function() { return this.count; }}",
want: `3`,
}, { // tests that depth is reported correctly
code: "{depths: [], step: function(log) { this.depths.push(log.stack.length()); }, fault: function() {}, result: function() { return this.depths; }}",
want: `[0,1,2]`,
}, { // tests to-string of opcodes
code: "{opcodes: [], step: function(log) { this.opcodes.push(log.op.toString()); }, fault: function() {}, result: function() { return this.opcodes; }}",
want: `["PUSH1","PUSH1","STOP"]`,
}, { // tests intrinsic gas
code: "{depths: [], step: function() {}, fault: function() {}, result: function(ctx) { return ctx.gasPrice+'.'+ctx.gasUsed+'.'+ctx.intrinsicGas; }}",
want: `"100000.6.21000"`,
},
} {
if have := execTracer(tt.code); tt.want != string(have) {
t.Errorf("testcase %d: expected return value to be %s got %s\n\tcode: %v", i, tt.want, string(have), tt.code)
}
}
}

Expand Down Expand Up @@ -187,9 +149,6 @@ func TestHaltBetweenSteps(t *testing.T) {
if err != nil {
t.Fatal(err)
}
// Needed for intrinsic gas computation
tracer.ctx["input"] = []byte{}

env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0)

Expand All @@ -202,19 +161,3 @@ func TestHaltBetweenSteps(t *testing.T) {
t.Errorf("Expected timeout error, got %v", err)
}
}

func TestIntrinsicGas(t *testing.T) {
vmctx := testCtx()
tracer, err := New("{depths: [], step: function() {}, fault: function() {}, result: function(ctx) { return ctx.gasPrice+'.'+ctx.gasUsed+'.'+ctx.intrinsicGas; }}", vmctx.txCtx)
if err != nil {
t.Fatal(err)
}

ret, err := runTrace(tracer, vmctx)
if err != nil {
t.Fatal(err)
}
if have, want := ret, []byte(`"100000.6.21000"`); !bytes.Equal(have, want) {
t.Errorf("Expected return value to be %s got %s", string(want), string(have))
}
}

0 comments on commit 87dffcf

Please sign in to comment.