github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/neatptc/tracers/tracer_test.go (about) 1 package tracers 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "math/big" 8 "testing" 9 "time" 10 11 "github.com/neatlab/neatio/chain/core/vm" 12 "github.com/neatlab/neatio/params" 13 "github.com/neatlab/neatio/utilities/common" 14 ) 15 16 type account struct{} 17 18 func (account) SubBalance(amount *big.Int) {} 19 func (account) AddBalance(amount *big.Int) {} 20 func (account) SetAddress(common.Address) {} 21 func (account) Value() *big.Int { return nil } 22 func (account) SetBalance(*big.Int) {} 23 func (account) SetNonce(uint64) {} 24 func (account) Balance() *big.Int { return nil } 25 func (account) Address() common.Address { return common.Address{} } 26 func (account) ReturnGas(*big.Int) {} 27 func (account) SetCode(common.Hash, []byte) {} 28 func (account) ForEachStorage(cb func(key, value common.Hash) bool) {} 29 30 func runTrace(tracer *Tracer) (json.RawMessage, error) { 31 env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) 32 33 contract := vm.NewContract(account{}, account{}, big.NewInt(0), 10000) 34 contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0} 35 36 _, err := env.Interpreter().Run(contract, []byte{}) 37 if err != nil { 38 return nil, err 39 } 40 return tracer.GetResult() 41 } 42 43 func TestTracing(t *testing.T) { 44 tracer, err := New("{count: 0, step: function() { this.count += 1; }, fault: function() {}, result: function() { return this.count; }}") 45 if err != nil { 46 t.Fatal(err) 47 } 48 49 ret, err := runTrace(tracer) 50 if err != nil { 51 t.Fatal(err) 52 } 53 if !bytes.Equal(ret, []byte("3")) { 54 t.Errorf("Expected return value to be 3, got %s", string(ret)) 55 } 56 } 57 58 func TestStack(t *testing.T) { 59 tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.stack.length()); }, fault: function() {}, result: function() { return this.depths; }}") 60 if err != nil { 61 t.Fatal(err) 62 } 63 64 ret, err := runTrace(tracer) 65 if err != nil { 66 t.Fatal(err) 67 } 68 if !bytes.Equal(ret, []byte("[0,1,2]")) { 69 t.Errorf("Expected return value to be [0,1,2], got %s", string(ret)) 70 } 71 } 72 73 func TestOpcodes(t *testing.T) { 74 tracer, err := New("{opcodes: [], step: function(log) { this.opcodes.push(log.op.toString()); }, fault: function() {}, result: function() { return this.opcodes; }}") 75 if err != nil { 76 t.Fatal(err) 77 } 78 79 ret, err := runTrace(tracer) 80 if err != nil { 81 t.Fatal(err) 82 } 83 if !bytes.Equal(ret, []byte("[\"PUSH1\",\"PUSH1\",\"STOP\"]")) { 84 t.Errorf("Expected return value to be [\"PUSH1\",\"PUSH1\",\"STOP\"], got %s", string(ret)) 85 } 86 } 87 88 func TestHalt(t *testing.T) { 89 t.Skip("duktape doesn't support abortion") 90 91 timeout := errors.New("stahp") 92 tracer, err := New("{step: function() { while(1); }, result: function() { return null; }}") 93 if err != nil { 94 t.Fatal(err) 95 } 96 97 go func() { 98 time.Sleep(1 * time.Second) 99 tracer.Stop(timeout) 100 }() 101 102 if _, err = runTrace(tracer); err.Error() != "stahp in server-side tracer function 'step'" { 103 t.Errorf("Expected timeout error, got %v", err) 104 } 105 } 106 107 func TestHaltBetweenSteps(t *testing.T) { 108 tracer, err := New("{step: function() {}, fault: function() {}, result: function() { return null; }}") 109 if err != nil { 110 t.Fatal(err) 111 } 112 113 env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) 114 contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0) 115 116 tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, contract, 0, nil) 117 timeout := errors.New("stahp") 118 tracer.Stop(timeout) 119 tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, contract, 0, nil) 120 121 if _, err := tracer.GetResult(); err.Error() != timeout.Error() { 122 t.Errorf("Expected timeout error, got %v", err) 123 } 124 }