github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/interop/runtime/util_test.go (about) 1 package runtime 2 3 import ( 4 "encoding/hex" 5 "testing" 6 7 "github.com/nspcc-dev/neo-go/internal/random" 8 "github.com/nspcc-dev/neo-go/pkg/core/interop" 9 "github.com/nspcc-dev/neo-go/pkg/core/state" 10 "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" 11 "github.com/nspcc-dev/neo-go/pkg/util" 12 "github.com/nspcc-dev/neo-go/pkg/vm" 13 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestGasLeft(t *testing.T) { 18 t.Run("no limit", func(t *testing.T) { 19 ic := &interop.Context{VM: vm.New()} 20 ic.VM.GasLimit = -1 21 ic.VM.AddGas(58) 22 require.NoError(t, GasLeft(ic)) 23 checkStack(t, ic.VM, -1) 24 }) 25 t.Run("with limit", func(t *testing.T) { 26 ic := &interop.Context{VM: vm.New()} 27 ic.VM.GasLimit = 100 28 ic.VM.AddGas(58) 29 require.NoError(t, GasLeft(ic)) 30 checkStack(t, ic.VM, 42) 31 }) 32 } 33 34 func TestRuntimeGetNotifications(t *testing.T) { 35 v := vm.New() 36 ic := &interop.Context{ 37 VM: v, 38 Notifications: []state.NotificationEvent{ 39 {ScriptHash: util.Uint160{1}, Name: "Event1", Item: stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray([]byte{11})})}, 40 {ScriptHash: util.Uint160{2}, Name: "Event2", Item: stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray([]byte{22})})}, 41 {ScriptHash: util.Uint160{1}, Name: "Event1", Item: stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray([]byte{33})})}, 42 }, 43 } 44 45 t.Run("NoFilter", func(t *testing.T) { 46 v.Estack().PushVal(stackitem.Null{}) 47 require.NoError(t, GetNotifications(ic)) 48 49 arr := v.Estack().Pop().Array() 50 require.Equal(t, len(ic.Notifications), len(arr)) 51 for i := range arr { 52 elem := arr[i].Value().([]stackitem.Item) 53 require.Equal(t, ic.Notifications[i].ScriptHash.BytesBE(), elem[0].Value()) 54 name, err := stackitem.ToString(elem[1]) 55 require.NoError(t, err) 56 require.Equal(t, ic.Notifications[i].Name, name) 57 ic.Notifications[i].Item.MarkAsReadOnly() // tiny hack for test to be able to compare object references. 58 require.Equal(t, ic.Notifications[i].Item, elem[2]) 59 } 60 }) 61 62 t.Run("WithFilter", func(t *testing.T) { 63 h := util.Uint160{2}.BytesBE() 64 v.Estack().PushVal(h) 65 require.NoError(t, GetNotifications(ic)) 66 67 arr := v.Estack().Pop().Array() 68 require.Equal(t, 1, len(arr)) 69 elem := arr[0].Value().([]stackitem.Item) 70 require.Equal(t, h, elem[0].Value()) 71 name, err := stackitem.ToString(elem[1]) 72 require.NoError(t, err) 73 require.Equal(t, ic.Notifications[1].Name, name) 74 require.Equal(t, ic.Notifications[1].Item, elem[2]) 75 }) 76 77 t.Run("Bad", func(t *testing.T) { 78 t.Run("not bytes", func(t *testing.T) { 79 v.Estack().PushVal(stackitem.NewInterop(util.Uint160{1})) 80 require.Error(t, GetNotifications(ic)) 81 }) 82 t.Run("not uint160", func(t *testing.T) { 83 v.Estack().PushVal([]byte{1, 2, 3}) 84 require.Error(t, GetNotifications(ic)) 85 }) 86 t.Run("too many notifications", func(t *testing.T) { 87 for i := 0; i <= vm.MaxStackSize; i++ { 88 ic.Notifications = append(ic.Notifications, state.NotificationEvent{ 89 ScriptHash: util.Uint160{3}, 90 Name: "Event3", 91 Item: stackitem.NewArray(nil), 92 }) 93 } 94 v.Estack().PushVal(stackitem.Null{}) 95 require.Error(t, GetNotifications(ic)) 96 }) 97 }) 98 } 99 100 func TestRuntimeGetInvocationCounter(t *testing.T) { 101 ic := &interop.Context{VM: vm.New(), Invocations: make(map[util.Uint160]int)} 102 h := random.Uint160() 103 ic.Invocations[h] = 42 104 105 t.Run("No invocations", func(t *testing.T) { 106 h1 := h 107 h1[0] ^= 0xFF 108 ic.VM.LoadScriptWithHash([]byte{1}, h1, callflag.NoneFlag) 109 // do not return an error in this case. 110 require.NoError(t, GetInvocationCounter(ic)) 111 checkStack(t, ic.VM, 1) 112 }) 113 t.Run("NonZero", func(t *testing.T) { 114 ic.VM.LoadScriptWithHash([]byte{1}, h, callflag.NoneFlag) 115 require.NoError(t, GetInvocationCounter(ic)) 116 checkStack(t, ic.VM, 42) 117 }) 118 } 119 120 // Test compatibility with C# implementation. 121 // https://github.com/neo-project/neo/blob/master/tests/neo.UnitTests/Cryptography/UT_Murmur128.cs 122 func TestMurmurCompat(t *testing.T) { 123 res := murmur128([]byte("hello"), 123) 124 require.Equal(t, "0bc59d0ad25fde2982ed65af61227a0e", hex.EncodeToString(res)) 125 126 res = murmur128([]byte("world"), 123) 127 require.Equal(t, "3d3810fed480472bd214a14023bb407f", hex.EncodeToString(res)) 128 129 res = murmur128([]byte("hello world"), 123) 130 require.Equal(t, "e0a0632d4f51302c55e3b3e48d28795d", hex.EncodeToString(res)) 131 132 bs, _ := hex.DecodeString("718f952132679baa9c5c2aa0d329fd2a") 133 res = murmur128(bs, 123) 134 require.Equal(t, "9b4aa747ff0cf4e41b3d96251551c8ae", hex.EncodeToString(res)) 135 }