2018-03-30 16:15:06 +00:00
|
|
|
package vm
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2019-10-17 14:10:00 +00:00
|
|
|
"encoding/binary"
|
2018-03-30 16:15:06 +00:00
|
|
|
"encoding/hex"
|
2020-04-28 08:24:02 +00:00
|
|
|
"fmt"
|
2018-04-02 15:04:42 +00:00
|
|
|
"math/big"
|
2018-03-30 16:15:06 +00:00
|
|
|
"math/rand"
|
|
|
|
"testing"
|
|
|
|
|
2020-04-21 13:45:48 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/internal/random"
|
2020-03-03 14:21:42 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
2018-03-30 16:15:06 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2019-10-22 10:44:14 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2018-03-30 16:15:06 +00:00
|
|
|
)
|
|
|
|
|
2019-12-18 16:49:56 +00:00
|
|
|
func fooInteropGetter(id uint32) *InteropFuncPrice {
|
2020-04-15 14:13:50 +00:00
|
|
|
if id == emit.InteropNameToID([]byte("foo")) {
|
2019-12-18 16:49:56 +00:00
|
|
|
return &InteropFuncPrice{func(evm *VM) error {
|
|
|
|
evm.Estack().PushVal(1)
|
|
|
|
return nil
|
|
|
|
}, 1}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-04-10 09:45:31 +00:00
|
|
|
func TestInteropHook(t *testing.T) {
|
2019-10-22 10:44:14 +00:00
|
|
|
v := New()
|
2019-12-18 16:49:56 +00:00
|
|
|
v.RegisterInteropGetter(fooInteropGetter)
|
2018-04-10 09:45:31 +00:00
|
|
|
|
2020-02-03 14:46:51 +00:00
|
|
|
buf := io.NewBufBinWriter()
|
|
|
|
emit.Syscall(buf.BinWriter, "foo")
|
|
|
|
emit.Opcode(buf.BinWriter, opcode.RET)
|
2018-04-10 09:45:31 +00:00
|
|
|
v.Load(buf.Bytes())
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, v)
|
2018-04-10 09:45:31 +00:00
|
|
|
assert.Equal(t, 1, v.estack.Len())
|
|
|
|
assert.Equal(t, big.NewInt(1), v.estack.Pop().value.Value())
|
|
|
|
}
|
|
|
|
|
2019-12-18 16:49:56 +00:00
|
|
|
func TestRegisterInteropGetter(t *testing.T) {
|
2019-10-22 10:44:14 +00:00
|
|
|
v := New()
|
2019-12-18 16:49:56 +00:00
|
|
|
currRegistered := len(v.getInterop)
|
|
|
|
v.RegisterInteropGetter(fooInteropGetter)
|
|
|
|
assert.Equal(t, currRegistered+1, len(v.getInterop))
|
2018-04-10 09:45:31 +00:00
|
|
|
}
|
|
|
|
|
2020-01-20 11:42:36 +00:00
|
|
|
func TestVM_SetPriceGetter(t *testing.T) {
|
|
|
|
v := New()
|
|
|
|
prog := []byte{
|
|
|
|
byte(opcode.PUSH4), byte(opcode.PUSH2),
|
|
|
|
byte(opcode.PUSHDATA1), 0x01, 0x01,
|
|
|
|
byte(opcode.PUSHDATA1), 0x02, 0xCA, 0xFE,
|
|
|
|
byte(opcode.PUSH4), byte(opcode.RET),
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("no price getter", func(t *testing.T) {
|
|
|
|
v.Load(prog)
|
|
|
|
runVM(t, v)
|
|
|
|
|
|
|
|
require.EqualValues(t, 0, v.GasConsumed())
|
|
|
|
})
|
|
|
|
|
|
|
|
v.SetPriceGetter(func(_ *VM, op opcode.Opcode, p []byte) util.Fixed8 {
|
|
|
|
if op == opcode.PUSH4 {
|
|
|
|
return 1
|
|
|
|
} else if op == opcode.PUSHDATA1 && bytes.Equal(p, []byte{0xCA, 0xFE}) {
|
|
|
|
return 7
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("with price getter", func(t *testing.T) {
|
|
|
|
v.Load(prog)
|
|
|
|
runVM(t, v)
|
|
|
|
|
2020-01-20 11:49:07 +00:00
|
|
|
require.EqualValues(t, 9, v.GasConsumed())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("with sufficient gas limit", func(t *testing.T) {
|
|
|
|
v.Load(prog)
|
|
|
|
v.SetGasLimit(9)
|
|
|
|
runVM(t, v)
|
|
|
|
|
|
|
|
require.EqualValues(t, 9, v.GasConsumed())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("with small gas limit", func(t *testing.T) {
|
|
|
|
v.Load(prog)
|
|
|
|
v.SetGasLimit(8)
|
|
|
|
checkVMFailed(t, v)
|
2020-01-20 11:42:36 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-12-10 16:13:29 +00:00
|
|
|
func TestBytesToPublicKey(t *testing.T) {
|
|
|
|
v := New()
|
|
|
|
cache := v.GetPublicKeys()
|
|
|
|
assert.Equal(t, 0, len(cache))
|
|
|
|
keyHex := "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"
|
|
|
|
keyBytes, _ := hex.DecodeString(keyHex)
|
|
|
|
key := v.bytesToPublicKey(keyBytes)
|
|
|
|
assert.NotNil(t, key)
|
|
|
|
key2 := v.bytesToPublicKey(keyBytes)
|
|
|
|
assert.Equal(t, key, key2)
|
|
|
|
|
|
|
|
cache = v.GetPublicKeys()
|
|
|
|
assert.Equal(t, 1, len(cache))
|
|
|
|
assert.NotNil(t, cache[string(keyBytes)])
|
|
|
|
|
|
|
|
keyBytes[0] = 0xff
|
|
|
|
require.Panics(t, func() { v.bytesToPublicKey(keyBytes) })
|
|
|
|
}
|
|
|
|
|
2018-03-30 16:15:06 +00:00
|
|
|
func TestPushBytes1to75(t *testing.T) {
|
2020-02-03 14:46:51 +00:00
|
|
|
buf := io.NewBufBinWriter()
|
2018-03-30 16:15:06 +00:00
|
|
|
for i := 1; i <= 75; i++ {
|
|
|
|
b := randomBytes(i)
|
2020-02-03 14:46:51 +00:00
|
|
|
emit.Bytes(buf.BinWriter, b)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(buf.Bytes())
|
2019-10-22 10:44:14 +00:00
|
|
|
err := vm.Step()
|
|
|
|
require.NoError(t, err)
|
2018-03-30 16:15:06 +00:00
|
|
|
|
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
|
|
|
|
elem := vm.estack.Pop()
|
2018-04-02 15:04:42 +00:00
|
|
|
assert.IsType(t, &ByteArrayItem{}, elem.value)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.IsType(t, elem.Bytes(), b)
|
|
|
|
assert.Equal(t, 0, vm.estack.Len())
|
|
|
|
|
2019-12-03 14:05:06 +00:00
|
|
|
errExec := vm.execute(nil, opcode.RET, nil)
|
2019-10-22 10:44:14 +00:00
|
|
|
require.NoError(t, errExec)
|
2018-03-30 16:15:06 +00:00
|
|
|
|
|
|
|
assert.Equal(t, 0, vm.astack.Len())
|
|
|
|
assert.Equal(t, 0, vm.istack.Len())
|
|
|
|
buf.Reset()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
func runVM(t *testing.T, vm *VM) {
|
|
|
|
err := vm.Run()
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, false, vm.HasFailed())
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkVMFailed(t *testing.T, vm *VM) {
|
|
|
|
err := vm.Run()
|
|
|
|
require.Error(t, err)
|
2019-09-23 15:46:47 +00:00
|
|
|
assert.Equal(t, true, vm.HasFailed())
|
2019-09-09 09:07:03 +00:00
|
|
|
}
|
|
|
|
|
2019-10-29 10:26:34 +00:00
|
|
|
func TestStackLimitPUSH1Good(t *testing.T) {
|
|
|
|
prog := make([]byte, MaxStackSize*2)
|
|
|
|
for i := 0; i < MaxStackSize; i++ {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog[i] = byte(opcode.PUSH1)
|
2019-10-29 10:26:34 +00:00
|
|
|
}
|
|
|
|
for i := MaxStackSize; i < MaxStackSize*2; i++ {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog[i] = byte(opcode.DROP)
|
2019-10-29 10:26:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
v := load(prog)
|
|
|
|
runVM(t, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStackLimitPUSH1Bad(t *testing.T) {
|
|
|
|
prog := make([]byte, MaxStackSize+1)
|
|
|
|
for i := range prog {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog[i] = byte(opcode.PUSH1)
|
2019-10-29 10:26:34 +00:00
|
|
|
}
|
|
|
|
v := load(prog)
|
|
|
|
checkVMFailed(t, v)
|
|
|
|
}
|
|
|
|
|
2020-04-21 13:45:48 +00:00
|
|
|
func testPUSHINT(t *testing.T, op opcode.Opcode, parameter []byte, expected *big.Int) {
|
|
|
|
prog := append([]byte{byte(op)}, parameter...)
|
|
|
|
v := load(prog)
|
|
|
|
runVM(t, v)
|
|
|
|
require.Equal(t, 1, v.estack.Len())
|
|
|
|
require.EqualValues(t, expected, v.estack.Pop().BigInt())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPUSHINT(t *testing.T) {
|
|
|
|
for i := byte(0); i < 5; i++ {
|
|
|
|
op := opcode.PUSHINT8 + opcode.Opcode(i)
|
|
|
|
t.Run(op.String(), func(t *testing.T) {
|
|
|
|
buf := random.Bytes((8 << i) / 8)
|
|
|
|
testPUSHINT(t, op, buf, emit.BytesToInt(buf))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-23 08:58:41 +00:00
|
|
|
func TestPUSHNULL(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.PUSHNULL, opcode.PUSHNULL, opcode.EQUAL)
|
|
|
|
v := load(prog)
|
|
|
|
require.NoError(t, v.Step())
|
|
|
|
require.Equal(t, 1, v.estack.Len())
|
|
|
|
runVM(t, v)
|
|
|
|
require.True(t, v.estack.Pop().Bool())
|
|
|
|
}
|
|
|
|
|
2020-03-23 09:26:26 +00:00
|
|
|
func TestISNULL(t *testing.T) {
|
|
|
|
t.Run("Integer", func(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.PUSH1, opcode.ISNULL)
|
|
|
|
v := load(prog)
|
|
|
|
runVM(t, v)
|
|
|
|
require.False(t, v.estack.Pop().Bool())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Null", func(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.PUSHNULL, opcode.ISNULL)
|
|
|
|
v := load(prog)
|
|
|
|
runVM(t, v)
|
|
|
|
require.True(t, v.estack.Pop().Bool())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-04-24 10:46:46 +00:00
|
|
|
func testISTYPE(t *testing.T, result bool, typ StackItemType, item StackItem) {
|
|
|
|
prog := []byte{byte(opcode.ISTYPE), byte(typ)}
|
|
|
|
v := load(prog)
|
|
|
|
v.estack.PushVal(item)
|
|
|
|
runVM(t, v)
|
|
|
|
require.Equal(t, 1, v.estack.Len())
|
|
|
|
require.Equal(t, result, v.estack.Pop().Bool())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestISTYPE(t *testing.T) {
|
|
|
|
t.Run("Integer", func(t *testing.T) {
|
|
|
|
testISTYPE(t, true, IntegerT, NewBigIntegerItem(big.NewInt(42)))
|
|
|
|
testISTYPE(t, false, IntegerT, NewByteArrayItem([]byte{}))
|
|
|
|
})
|
|
|
|
t.Run("Boolean", func(t *testing.T) {
|
|
|
|
testISTYPE(t, true, BooleanT, NewBoolItem(true))
|
|
|
|
testISTYPE(t, false, BooleanT, NewByteArrayItem([]byte{}))
|
|
|
|
})
|
|
|
|
t.Run("ByteArray", func(t *testing.T) {
|
|
|
|
testISTYPE(t, true, ByteArrayT, NewByteArrayItem([]byte{}))
|
|
|
|
testISTYPE(t, false, ByteArrayT, NewBigIntegerItem(big.NewInt(42)))
|
|
|
|
})
|
|
|
|
t.Run("Array", func(t *testing.T) {
|
|
|
|
testISTYPE(t, true, ArrayT, NewArrayItem([]StackItem{}))
|
|
|
|
testISTYPE(t, false, ArrayT, NewByteArrayItem([]byte{}))
|
|
|
|
})
|
|
|
|
t.Run("Struct", func(t *testing.T) {
|
|
|
|
testISTYPE(t, true, StructT, NewStructItem([]StackItem{}))
|
|
|
|
testISTYPE(t, false, StructT, NewByteArrayItem([]byte{}))
|
|
|
|
})
|
|
|
|
t.Run("Map", func(t *testing.T) {
|
|
|
|
testISTYPE(t, true, MapT, NewMapItem())
|
|
|
|
testISTYPE(t, false, MapT, NewByteArrayItem([]byte{}))
|
|
|
|
})
|
|
|
|
t.Run("Interop", func(t *testing.T) {
|
|
|
|
testISTYPE(t, true, InteropT, NewInteropItem(42))
|
|
|
|
testISTYPE(t, false, InteropT, NewByteArrayItem([]byte{}))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-04-28 08:24:02 +00:00
|
|
|
func testCONVERT(isErr bool, to StackItemType, item, res StackItem) func(t *testing.T) {
|
|
|
|
return func(t *testing.T) {
|
|
|
|
prog := []byte{byte(opcode.CONVERT), byte(to)}
|
|
|
|
v := load(prog)
|
|
|
|
v.estack.PushVal(item)
|
|
|
|
if isErr {
|
|
|
|
checkVMFailed(t, v)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
runVM(t, v)
|
|
|
|
require.Equal(t, 1, v.estack.Len())
|
|
|
|
require.Equal(t, res, v.estack.Pop().value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCONVERT(t *testing.T) {
|
|
|
|
type convertTC struct {
|
|
|
|
item, res StackItem
|
|
|
|
}
|
|
|
|
arr := []StackItem{
|
|
|
|
NewBigIntegerItem(big.NewInt(7)),
|
|
|
|
NewByteArrayItem([]byte{4, 8, 15}),
|
|
|
|
}
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(NewByteArrayItem([]byte{1}), NewByteArrayItem([]byte{2}))
|
|
|
|
|
|
|
|
getName := func(item StackItem, typ StackItemType) string { return fmt.Sprintf("%s->%s", item, typ) }
|
|
|
|
|
|
|
|
t.Run("->Bool", func(t *testing.T) {
|
|
|
|
testBool := func(a, b StackItem) func(t *testing.T) {
|
|
|
|
return testCONVERT(false, BooleanT, a, b)
|
|
|
|
}
|
|
|
|
|
|
|
|
trueCases := []StackItem{
|
|
|
|
NewBoolItem(true), NewBigIntegerItem(big.NewInt(11)), NewByteArrayItem([]byte{1, 2, 3}),
|
|
|
|
NewArrayItem(arr), NewArrayItem(nil),
|
|
|
|
NewStructItem(arr), NewStructItem(nil),
|
|
|
|
NewMapItem(), m, NewInteropItem(struct{}{}),
|
|
|
|
}
|
|
|
|
for i := range trueCases {
|
|
|
|
t.Run(getName(trueCases[i], BooleanT), testBool(trueCases[i], NewBoolItem(true)))
|
|
|
|
}
|
|
|
|
|
|
|
|
falseCases := []StackItem{
|
|
|
|
NewBigIntegerItem(big.NewInt(0)), NewByteArrayItem([]byte{0, 0}), NewBoolItem(false),
|
|
|
|
}
|
|
|
|
for i := range falseCases {
|
|
|
|
testBool(falseCases[i], NewBoolItem(false))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("compound/interop -> basic", func(t *testing.T) {
|
|
|
|
types := []StackItemType{IntegerT, ByteArrayT}
|
|
|
|
items := []StackItem{NewArrayItem(nil), NewStructItem(nil), NewMapItem(), NewInteropItem(struct{}{})}
|
|
|
|
for _, typ := range types {
|
|
|
|
for j := range items {
|
|
|
|
t.Run(getName(items[j], typ), testCONVERT(true, typ, items[j], nil))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("primitive -> Integer/ByteArray", func(t *testing.T) {
|
|
|
|
n := big.NewInt(42)
|
|
|
|
b := emit.IntToBytes(n)
|
|
|
|
|
|
|
|
itemInt := NewBigIntegerItem(n)
|
|
|
|
itemBytes := NewByteArrayItem(b)
|
|
|
|
|
|
|
|
trueCases := map[StackItemType][]convertTC{
|
|
|
|
IntegerT: {
|
|
|
|
{itemInt, itemInt},
|
|
|
|
{itemBytes, itemInt},
|
|
|
|
{NewBoolItem(true), NewBigIntegerItem(big.NewInt(1))},
|
|
|
|
{NewBoolItem(false), NewBigIntegerItem(big.NewInt(0))},
|
|
|
|
},
|
|
|
|
ByteArrayT: {
|
|
|
|
{itemInt, itemBytes},
|
|
|
|
{itemBytes, itemBytes},
|
|
|
|
{NewBoolItem(true), NewByteArrayItem([]byte{1})},
|
|
|
|
{NewBoolItem(false), NewByteArrayItem([]byte{0})},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for typ := range trueCases {
|
|
|
|
for _, tc := range trueCases[typ] {
|
|
|
|
t.Run(getName(tc.item, typ), testCONVERT(false, typ, tc.item, tc.res))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Struct<->Array", func(t *testing.T) {
|
|
|
|
arrayItem := NewArrayItem(arr)
|
|
|
|
structItem := NewStructItem(arr)
|
|
|
|
t.Run("Array->Array", testCONVERT(false, ArrayT, arrayItem, arrayItem))
|
|
|
|
t.Run("Array->Struct", testCONVERT(false, StructT, arrayItem, structItem))
|
|
|
|
t.Run("Struct->Array", testCONVERT(false, ArrayT, structItem, arrayItem))
|
|
|
|
t.Run("Struct->Struct", testCONVERT(false, StructT, structItem, structItem))
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Map->Map", testCONVERT(false, MapT, m, m))
|
|
|
|
|
|
|
|
t.Run("Null->", func(t *testing.T) {
|
|
|
|
types := []StackItemType{
|
|
|
|
BooleanT, ByteArrayT, IntegerT, ArrayT, StructT, MapT, InteropT,
|
|
|
|
}
|
|
|
|
for i := range types {
|
|
|
|
t.Run(types[i].String(), testCONVERT(false, types[i], NullItem{}, NullItem{}))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("->Any", func(t *testing.T) {
|
|
|
|
items := []StackItem{
|
|
|
|
NewBigIntegerItem(big.NewInt(1)), NewByteArrayItem([]byte{1}), NewBoolItem(true),
|
|
|
|
NewArrayItem(arr), NewStructItem(arr), m, NewInteropItem(struct{}{}),
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range items {
|
|
|
|
t.Run(items[i].String(), testCONVERT(true, AnyT, items[i], nil))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-10-29 10:26:34 +00:00
|
|
|
// appendBigStruct returns a program which:
|
|
|
|
// 1. pushes size Structs on stack
|
|
|
|
// 2. packs them into a new struct
|
|
|
|
// 3. appends them to a zero-length array
|
|
|
|
// Resulting stack size consists of:
|
|
|
|
// - struct (size+1)
|
|
|
|
// - array (1) of struct (size+1)
|
|
|
|
// which equals to size*2+3 elements in total.
|
2019-12-03 14:05:06 +00:00
|
|
|
func appendBigStruct(size uint16) []opcode.Opcode {
|
|
|
|
prog := make([]opcode.Opcode, size*2)
|
2019-10-29 10:26:34 +00:00
|
|
|
for i := uint16(0); i < size; i++ {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog[i*2] = opcode.PUSH0
|
|
|
|
prog[i*2+1] = opcode.NEWSTRUCT
|
2019-10-29 10:26:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return append(prog,
|
2020-04-21 13:45:48 +00:00
|
|
|
opcode.PUSHINT16, opcode.Opcode(size), opcode.Opcode(size>>8), // LE
|
2019-12-03 14:05:06 +00:00
|
|
|
opcode.PACK, opcode.NEWSTRUCT,
|
|
|
|
opcode.DUP,
|
|
|
|
opcode.PUSH0, opcode.NEWARRAY, opcode.TOALTSTACK, opcode.DUPFROMALTSTACK,
|
|
|
|
opcode.SWAP,
|
|
|
|
opcode.APPEND, opcode.RET)
|
2019-10-29 10:26:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestStackLimitAPPENDStructGood(t *testing.T) {
|
|
|
|
prog := makeProgram(appendBigStruct(MaxStackSize/2 - 2)...)
|
|
|
|
v := load(prog)
|
|
|
|
runVM(t, v) // size = 2047 = (Max/2-2)*2+3 = Max-1
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStackLimitAPPENDStructBad(t *testing.T) {
|
|
|
|
prog := makeProgram(appendBigStruct(MaxStackSize/2 - 1)...)
|
|
|
|
v := load(prog)
|
|
|
|
checkVMFailed(t, v) // size = 2049 = (Max/2-1)*2+3 = Max+1
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStackLimit(t *testing.T) {
|
|
|
|
expected := []struct {
|
2019-12-03 14:05:06 +00:00
|
|
|
inst opcode.Opcode
|
2019-10-29 10:26:34 +00:00
|
|
|
size int
|
|
|
|
}{
|
2019-12-03 14:05:06 +00:00
|
|
|
{opcode.PUSH2, 1},
|
|
|
|
{opcode.NEWARRAY, 3}, // array + 2 items
|
|
|
|
{opcode.TOALTSTACK, 3},
|
|
|
|
{opcode.DUPFROMALTSTACK, 4},
|
|
|
|
{opcode.NEWSTRUCT, 6}, // all items are copied
|
|
|
|
{opcode.NEWMAP, 7},
|
|
|
|
{opcode.DUP, 8},
|
|
|
|
{opcode.PUSH2, 9},
|
|
|
|
{opcode.DUPFROMALTSTACK, 10},
|
|
|
|
{opcode.SETITEM, 8}, // -3 items and 1 new element in map
|
|
|
|
{opcode.DUP, 9},
|
|
|
|
{opcode.PUSH2, 10},
|
|
|
|
{opcode.DUPFROMALTSTACK, 11},
|
|
|
|
{opcode.SETITEM, 8}, // -3 items and no new elements in map
|
|
|
|
{opcode.DUP, 9},
|
|
|
|
{opcode.PUSH2, 10},
|
|
|
|
{opcode.REMOVE, 7}, // as we have right after NEWMAP
|
|
|
|
{opcode.DROP, 6}, // DROP map with no elements
|
2019-10-29 10:26:34 +00:00
|
|
|
}
|
|
|
|
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := make([]opcode.Opcode, len(expected))
|
2019-10-29 10:26:34 +00:00
|
|
|
for i := range expected {
|
|
|
|
prog[i] = expected[i].inst
|
|
|
|
}
|
|
|
|
|
|
|
|
vm := load(makeProgram(prog...))
|
|
|
|
for i := range expected {
|
|
|
|
require.NoError(t, vm.Step())
|
|
|
|
require.Equal(t, expected[i].size, vm.size)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-30 16:15:06 +00:00
|
|
|
func TestPushm1to16(t *testing.T) {
|
2019-01-25 11:20:35 +00:00
|
|
|
var prog []byte
|
2019-12-03 14:05:06 +00:00
|
|
|
for i := int(opcode.PUSHM1); i <= int(opcode.PUSH16); i++ {
|
2018-03-30 16:15:06 +00:00
|
|
|
if i == 80 {
|
|
|
|
continue // opcode layout we got here.
|
|
|
|
}
|
|
|
|
prog = append(prog, byte(i))
|
|
|
|
}
|
|
|
|
|
|
|
|
vm := load(prog)
|
2019-12-03 14:05:06 +00:00
|
|
|
for i := int(opcode.PUSHM1); i <= int(opcode.PUSH16); i++ {
|
2019-10-22 10:44:14 +00:00
|
|
|
err := vm.Step()
|
|
|
|
require.NoError(t, err)
|
2018-03-30 16:15:06 +00:00
|
|
|
|
|
|
|
elem := vm.estack.Pop()
|
2019-12-03 14:05:06 +00:00
|
|
|
val := i - int(opcode.PUSH1) + 1
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, elem.BigInt().Int64(), int64(val))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-11 08:52:39 +00:00
|
|
|
func TestPushData1BadNoN(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := []byte{byte(opcode.PUSHDATA1)}
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 08:52:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestPushData1BadN(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := []byte{byte(opcode.PUSHDATA1), 1}
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 08:52:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestPushData1Good(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PUSHDATA1, 3, 1, 2, 3)
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-11 08:52:39 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, []byte{1, 2, 3}, vm.estack.Pop().Bytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPushData2BadNoN(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := []byte{byte(opcode.PUSHDATA2)}
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 08:52:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestPushData2ShortN(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := []byte{byte(opcode.PUSHDATA2), 0}
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 08:52:39 +00:00
|
|
|
}
|
2018-03-30 16:15:06 +00:00
|
|
|
|
2019-09-11 08:52:39 +00:00
|
|
|
func TestPushData2BadN(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := []byte{byte(opcode.PUSHDATA2), 1, 0}
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 08:52:39 +00:00
|
|
|
func TestPushData2Good(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PUSHDATA2, 3, 0, 1, 2, 3)
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-11 08:52:39 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, []byte{1, 2, 3}, vm.estack.Pop().Bytes())
|
|
|
|
}
|
2018-03-30 16:15:06 +00:00
|
|
|
|
2019-09-11 08:52:39 +00:00
|
|
|
func TestPushData4BadNoN(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := []byte{byte(opcode.PUSHDATA4)}
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 08:52:39 +00:00
|
|
|
func TestPushData4BadN(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := []byte{byte(opcode.PUSHDATA4), 1, 0, 0, 0}
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 08:52:39 +00:00
|
|
|
}
|
2018-03-30 16:15:06 +00:00
|
|
|
|
2019-09-11 08:52:39 +00:00
|
|
|
func TestPushData4ShortN(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := []byte{byte(opcode.PUSHDATA4), 0, 0, 0}
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 08:52:39 +00:00
|
|
|
}
|
|
|
|
|
2019-10-17 14:10:00 +00:00
|
|
|
func TestPushData4BigN(t *testing.T) {
|
|
|
|
prog := make([]byte, 1+4+MaxItemSize+1)
|
2019-12-03 14:05:06 +00:00
|
|
|
prog[0] = byte(opcode.PUSHDATA4)
|
2019-10-17 14:10:00 +00:00
|
|
|
binary.LittleEndian.PutUint32(prog[1:], MaxItemSize+1)
|
|
|
|
|
|
|
|
vm := load(prog)
|
|
|
|
vm.Run()
|
|
|
|
assert.Equal(t, true, vm.HasFailed())
|
|
|
|
}
|
|
|
|
|
2019-09-11 08:52:39 +00:00
|
|
|
func TestPushData4Good(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PUSHDATA4, 3, 0, 0, 0, 1, 2, 3)
|
2019-09-11 08:52:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-11 08:52:39 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, []byte{1, 2, 3}, vm.estack.Pop().Bytes())
|
2018-03-30 16:15:06 +00:00
|
|
|
}
|
|
|
|
|
2019-11-13 12:29:27 +00:00
|
|
|
func getEnumeratorProg(n int, isIter bool) (prog []byte) {
|
2019-11-13 11:34:03 +00:00
|
|
|
prog = append(prog, byte(opcode.TOALTSTACK))
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
prog = append(prog, byte(opcode.DUPFROMALTSTACK))
|
|
|
|
prog = append(prog, getSyscallProg("Neo.Enumerator.Next")...)
|
|
|
|
prog = append(prog, byte(opcode.DUPFROMALTSTACK))
|
|
|
|
prog = append(prog, getSyscallProg("Neo.Enumerator.Value")...)
|
2019-11-13 12:29:27 +00:00
|
|
|
if isIter {
|
|
|
|
prog = append(prog, byte(opcode.DUPFROMALTSTACK))
|
|
|
|
prog = append(prog, getSyscallProg("Neo.Iterator.Key")...)
|
|
|
|
}
|
2019-11-13 11:34:03 +00:00
|
|
|
}
|
|
|
|
prog = append(prog, byte(opcode.DUPFROMALTSTACK))
|
|
|
|
prog = append(prog, getSyscallProg("Neo.Enumerator.Next")...)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkEnumeratorStack(t *testing.T, vm *VM, arr []StackItem) {
|
|
|
|
require.Equal(t, len(arr)+1, vm.estack.Len())
|
|
|
|
require.Equal(t, NewBoolItem(false), vm.estack.Peek(0).value)
|
|
|
|
for i := 0; i < len(arr); i++ {
|
|
|
|
require.Equal(t, arr[i], vm.estack.Peek(i+1).value, "pos: %d", i+1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func testIterableCreate(t *testing.T, typ string) {
|
2019-11-13 12:29:27 +00:00
|
|
|
isIter := typ == "Iterator"
|
2019-11-13 11:34:03 +00:00
|
|
|
prog := getSyscallProg("Neo." + typ + ".Create")
|
2019-11-13 12:29:27 +00:00
|
|
|
prog = append(prog, getEnumeratorProg(2, isIter)...)
|
2019-11-13 11:34:03 +00:00
|
|
|
|
|
|
|
vm := load(prog)
|
|
|
|
arr := []StackItem{
|
2020-04-16 12:28:34 +00:00
|
|
|
NewBigIntegerItem(big.NewInt(42)),
|
2019-11-13 11:34:03 +00:00
|
|
|
NewByteArrayItem([]byte{3, 2, 1}),
|
|
|
|
}
|
|
|
|
vm.estack.Push(&Element{value: NewArrayItem(arr)})
|
|
|
|
|
|
|
|
runVM(t, vm)
|
2019-11-13 12:29:27 +00:00
|
|
|
if isIter {
|
|
|
|
checkEnumeratorStack(t, vm, []StackItem{
|
|
|
|
makeStackItem(1), arr[1], NewBoolItem(true),
|
|
|
|
makeStackItem(0), arr[0], NewBoolItem(true),
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
checkEnumeratorStack(t, vm, []StackItem{
|
|
|
|
arr[1], NewBoolItem(true),
|
|
|
|
arr[0], NewBoolItem(true),
|
|
|
|
})
|
|
|
|
}
|
2019-11-13 11:34:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEnumeratorCreate(t *testing.T) {
|
|
|
|
testIterableCreate(t, "Enumerator")
|
|
|
|
}
|
|
|
|
|
2019-11-13 12:29:27 +00:00
|
|
|
func TestIteratorCreate(t *testing.T) {
|
|
|
|
testIterableCreate(t, "Iterator")
|
|
|
|
}
|
|
|
|
|
|
|
|
func testIterableConcat(t *testing.T, typ string) {
|
|
|
|
isIter := typ == "Iterator"
|
|
|
|
prog := getSyscallProg("Neo." + typ + ".Create")
|
2019-11-13 11:34:03 +00:00
|
|
|
prog = append(prog, byte(opcode.SWAP))
|
2019-11-13 12:29:27 +00:00
|
|
|
prog = append(prog, getSyscallProg("Neo."+typ+".Create")...)
|
|
|
|
prog = append(prog, getSyscallProg("Neo."+typ+".Concat")...)
|
|
|
|
prog = append(prog, getEnumeratorProg(3, isIter)...)
|
2019-11-13 11:34:03 +00:00
|
|
|
vm := load(prog)
|
|
|
|
|
|
|
|
arr := []StackItem{
|
|
|
|
NewBoolItem(false),
|
2020-04-16 12:28:34 +00:00
|
|
|
NewBigIntegerItem(big.NewInt(123)),
|
2019-11-13 11:34:03 +00:00
|
|
|
NewMapItem(),
|
|
|
|
}
|
|
|
|
vm.estack.Push(&Element{value: NewArrayItem(arr[:1])})
|
|
|
|
vm.estack.Push(&Element{value: NewArrayItem(arr[1:])})
|
|
|
|
|
|
|
|
runVM(t, vm)
|
2019-11-13 12:29:27 +00:00
|
|
|
|
|
|
|
if isIter {
|
|
|
|
// Yes, this is how iterators are concatenated in reference VM
|
|
|
|
// https://github.com/neo-project/neo/blob/master-2.x/neo.UnitTests/UT_ConcatenatedIterator.cs#L54
|
|
|
|
checkEnumeratorStack(t, vm, []StackItem{
|
|
|
|
makeStackItem(1), arr[2], NewBoolItem(true),
|
|
|
|
makeStackItem(0), arr[1], NewBoolItem(true),
|
|
|
|
makeStackItem(0), arr[0], NewBoolItem(true),
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
checkEnumeratorStack(t, vm, []StackItem{
|
|
|
|
arr[2], NewBoolItem(true),
|
|
|
|
arr[1], NewBoolItem(true),
|
|
|
|
arr[0], NewBoolItem(true),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEnumeratorConcat(t *testing.T) {
|
|
|
|
testIterableConcat(t, "Enumerator")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIteratorConcat(t *testing.T) {
|
|
|
|
testIterableConcat(t, "Iterator")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIteratorKeys(t *testing.T) {
|
|
|
|
prog := getSyscallProg("Neo.Iterator.Create")
|
|
|
|
prog = append(prog, getSyscallProg("Neo.Iterator.Keys")...)
|
|
|
|
prog = append(prog, byte(opcode.TOALTSTACK), byte(opcode.DUPFROMALTSTACK))
|
|
|
|
prog = append(prog, getEnumeratorProg(2, false)...)
|
|
|
|
|
|
|
|
v := load(prog)
|
|
|
|
arr := NewArrayItem([]StackItem{
|
|
|
|
NewBoolItem(false),
|
2020-04-16 12:28:34 +00:00
|
|
|
NewBigIntegerItem(big.NewInt(42)),
|
2019-11-13 11:34:03 +00:00
|
|
|
})
|
2019-11-13 12:29:27 +00:00
|
|
|
v.estack.PushVal(arr)
|
|
|
|
|
|
|
|
runVM(t, v)
|
|
|
|
|
|
|
|
checkEnumeratorStack(t, v, []StackItem{
|
2020-04-16 12:28:34 +00:00
|
|
|
NewBigIntegerItem(big.NewInt(1)), NewBoolItem(true),
|
|
|
|
NewBigIntegerItem(big.NewInt(0)), NewBoolItem(true),
|
2019-11-13 12:29:27 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIteratorValues(t *testing.T) {
|
|
|
|
prog := getSyscallProg("Neo.Iterator.Create")
|
|
|
|
prog = append(prog, getSyscallProg("Neo.Iterator.Values")...)
|
|
|
|
prog = append(prog, byte(opcode.TOALTSTACK), byte(opcode.DUPFROMALTSTACK))
|
|
|
|
prog = append(prog, getEnumeratorProg(2, false)...)
|
|
|
|
|
|
|
|
v := load(prog)
|
|
|
|
m := NewMapItem()
|
2020-04-16 12:28:34 +00:00
|
|
|
m.Add(NewBigIntegerItem(big.NewInt(1)), NewBoolItem(false))
|
2019-11-13 12:29:27 +00:00
|
|
|
m.Add(NewByteArrayItem([]byte{32}), NewByteArrayItem([]byte{7}))
|
|
|
|
v.estack.PushVal(m)
|
|
|
|
|
|
|
|
runVM(t, v)
|
|
|
|
require.Equal(t, 5, v.estack.Len())
|
|
|
|
require.Equal(t, NewBoolItem(false), v.estack.Peek(0).value)
|
|
|
|
|
|
|
|
// Map values can be enumerated in any order.
|
|
|
|
i1, i2 := 1, 3
|
|
|
|
if _, ok := v.estack.Peek(i1).value.(*BoolItem); !ok {
|
|
|
|
i1, i2 = i2, i1
|
|
|
|
}
|
|
|
|
|
|
|
|
require.Equal(t, NewBoolItem(false), v.estack.Peek(i1).value)
|
|
|
|
require.Equal(t, NewByteArrayItem([]byte{7}), v.estack.Peek(i2).value)
|
|
|
|
|
|
|
|
require.Equal(t, NewBoolItem(true), v.estack.Peek(2).value)
|
|
|
|
require.Equal(t, NewBoolItem(true), v.estack.Peek(4).value)
|
2019-11-13 11:34:03 +00:00
|
|
|
}
|
|
|
|
|
2019-11-05 08:36:13 +00:00
|
|
|
func getSyscallProg(name string) (prog []byte) {
|
2020-04-15 14:40:05 +00:00
|
|
|
buf := io.NewBufBinWriter()
|
|
|
|
emit.Syscall(buf.BinWriter, name)
|
|
|
|
return buf.Bytes()
|
2019-11-05 08:36:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getSerializeProg() (prog []byte) {
|
|
|
|
prog = append(prog, getSyscallProg("Neo.Runtime.Serialize")...)
|
|
|
|
prog = append(prog, getSyscallProg("Neo.Runtime.Deserialize")...)
|
2019-12-03 14:05:06 +00:00
|
|
|
prog = append(prog, byte(opcode.RET))
|
2019-11-05 08:36:13 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func testSerialize(t *testing.T, vm *VM) {
|
|
|
|
err := vm.Step()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, vm.estack.Len())
|
|
|
|
require.IsType(t, (*ByteArrayItem)(nil), vm.estack.Top().value)
|
|
|
|
|
|
|
|
err = vm.Step()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, vm.estack.Len())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSerializeBool(t *testing.T) {
|
|
|
|
vm := load(getSerializeProg())
|
|
|
|
vm.estack.PushVal(true)
|
|
|
|
|
|
|
|
testSerialize(t, vm)
|
|
|
|
|
|
|
|
require.IsType(t, (*BoolItem)(nil), vm.estack.Top().value)
|
|
|
|
require.Equal(t, true, vm.estack.Top().Bool())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSerializeByteArray(t *testing.T) {
|
|
|
|
vm := load(getSerializeProg())
|
|
|
|
value := []byte{1, 2, 3}
|
|
|
|
vm.estack.PushVal(value)
|
|
|
|
|
|
|
|
testSerialize(t, vm)
|
|
|
|
|
|
|
|
require.IsType(t, (*ByteArrayItem)(nil), vm.estack.Top().value)
|
|
|
|
require.Equal(t, value, vm.estack.Top().Bytes())
|
|
|
|
}
|
|
|
|
|
2019-11-05 09:07:08 +00:00
|
|
|
func TestSerializeInteger(t *testing.T) {
|
|
|
|
vm := load(getSerializeProg())
|
|
|
|
value := int64(123)
|
|
|
|
vm.estack.PushVal(value)
|
|
|
|
|
|
|
|
testSerialize(t, vm)
|
|
|
|
|
|
|
|
require.IsType(t, (*BigIntegerItem)(nil), vm.estack.Top().value)
|
|
|
|
require.Equal(t, value, vm.estack.Top().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-11-05 09:25:15 +00:00
|
|
|
func TestSerializeArray(t *testing.T) {
|
|
|
|
vm := load(getSerializeProg())
|
|
|
|
item := NewArrayItem([]StackItem{
|
|
|
|
makeStackItem(true),
|
|
|
|
makeStackItem(123),
|
|
|
|
NewMapItem(),
|
|
|
|
})
|
|
|
|
|
|
|
|
vm.estack.Push(&Element{value: item})
|
|
|
|
|
|
|
|
testSerialize(t, vm)
|
|
|
|
|
|
|
|
require.IsType(t, (*ArrayItem)(nil), vm.estack.Top().value)
|
|
|
|
require.Equal(t, item.value, vm.estack.Top().Array())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSerializeArrayBad(t *testing.T) {
|
|
|
|
vm := load(getSerializeProg())
|
2020-04-24 10:48:19 +00:00
|
|
|
item := NewArrayItem(makeArrayOfType(2, BooleanT))
|
2019-11-05 09:25:15 +00:00
|
|
|
item.value[1] = item
|
|
|
|
|
|
|
|
vm.estack.Push(&Element{value: item})
|
|
|
|
|
|
|
|
err := vm.Step()
|
|
|
|
require.Error(t, err)
|
|
|
|
require.True(t, vm.HasFailed())
|
|
|
|
}
|
|
|
|
|
2019-11-15 09:47:58 +00:00
|
|
|
func TestSerializeDupInteger(t *testing.T) {
|
|
|
|
prog := []byte{
|
2019-12-03 14:05:06 +00:00
|
|
|
byte(opcode.PUSH0), byte(opcode.NEWARRAY),
|
|
|
|
byte(opcode.DUP), byte(opcode.PUSH2), byte(opcode.DUP), byte(opcode.TOALTSTACK), byte(opcode.APPEND),
|
|
|
|
byte(opcode.DUP), byte(opcode.FROMALTSTACK), byte(opcode.APPEND),
|
2019-11-15 09:47:58 +00:00
|
|
|
}
|
|
|
|
vm := load(append(prog, getSerializeProg()...))
|
|
|
|
|
|
|
|
runVM(t, vm)
|
|
|
|
}
|
|
|
|
|
2019-11-05 09:25:15 +00:00
|
|
|
func TestSerializeStruct(t *testing.T) {
|
|
|
|
vm := load(getSerializeProg())
|
|
|
|
item := NewStructItem([]StackItem{
|
|
|
|
makeStackItem(true),
|
|
|
|
makeStackItem(123),
|
|
|
|
NewMapItem(),
|
|
|
|
})
|
|
|
|
|
|
|
|
vm.estack.Push(&Element{value: item})
|
|
|
|
|
|
|
|
testSerialize(t, vm)
|
|
|
|
|
|
|
|
require.IsType(t, (*StructItem)(nil), vm.estack.Top().value)
|
|
|
|
require.Equal(t, item.value, vm.estack.Top().Array())
|
|
|
|
}
|
|
|
|
|
2019-11-05 14:04:14 +00:00
|
|
|
func TestDeserializeUnknown(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := append(getSyscallProg("Neo.Runtime.Deserialize"), byte(opcode.RET))
|
2019-11-05 14:04:14 +00:00
|
|
|
vm := load(prog)
|
|
|
|
|
2020-04-16 12:28:34 +00:00
|
|
|
data, err := SerializeItem(NewBigIntegerItem(big.NewInt(123)))
|
2019-11-05 14:04:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
data[0] = 0xFF
|
|
|
|
vm.estack.PushVal(data)
|
|
|
|
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
2019-11-05 08:57:55 +00:00
|
|
|
func TestSerializeMap(t *testing.T) {
|
|
|
|
vm := load(getSerializeProg())
|
|
|
|
item := NewMapItem()
|
|
|
|
item.Add(makeStackItem(true), makeStackItem([]byte{1, 2, 3}))
|
|
|
|
item.Add(makeStackItem([]byte{0}), makeStackItem(false))
|
|
|
|
|
|
|
|
vm.estack.Push(&Element{value: item})
|
|
|
|
|
|
|
|
testSerialize(t, vm)
|
|
|
|
|
|
|
|
require.IsType(t, (*MapItem)(nil), vm.estack.Top().value)
|
|
|
|
require.Equal(t, item.value, vm.estack.Top().value.(*MapItem).value)
|
|
|
|
}
|
|
|
|
|
2020-03-28 14:25:42 +00:00
|
|
|
func TestSerializeMapCompat(t *testing.T) {
|
2020-04-24 10:46:46 +00:00
|
|
|
resHex := "480128036b6579280576616c7565"
|
2020-03-28 14:25:42 +00:00
|
|
|
res, err := hex.DecodeString(resHex)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-04-15 14:40:05 +00:00
|
|
|
// Create a map, push key and value, add KV to map, serialize.
|
|
|
|
buf := io.NewBufBinWriter()
|
|
|
|
emit.Opcode(buf.BinWriter, opcode.NEWMAP)
|
|
|
|
emit.Opcode(buf.BinWriter, opcode.DUP)
|
|
|
|
emit.Bytes(buf.BinWriter, []byte("key"))
|
|
|
|
emit.Bytes(buf.BinWriter, []byte("value"))
|
|
|
|
emit.Opcode(buf.BinWriter, opcode.SETITEM)
|
|
|
|
emit.Syscall(buf.BinWriter, "Neo.Runtime.Serialize")
|
|
|
|
require.NoError(t, buf.Err)
|
|
|
|
|
|
|
|
vm := load(buf.Bytes())
|
2020-03-28 14:25:42 +00:00
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, res, vm.estack.Pop().Bytes())
|
|
|
|
}
|
|
|
|
|
2019-11-05 14:04:14 +00:00
|
|
|
func TestSerializeInterop(t *testing.T) {
|
|
|
|
vm := load(getSerializeProg())
|
|
|
|
item := NewInteropItem("kek")
|
|
|
|
|
|
|
|
vm.estack.Push(&Element{value: item})
|
|
|
|
|
|
|
|
err := vm.Step()
|
|
|
|
require.Error(t, err)
|
|
|
|
require.True(t, vm.HasFailed())
|
|
|
|
}
|
|
|
|
|
2019-10-29 08:01:06 +00:00
|
|
|
func callNTimes(n uint16) []byte {
|
|
|
|
return makeProgram(
|
2020-04-21 13:45:48 +00:00
|
|
|
opcode.PUSHINT16, opcode.Opcode(n), opcode.Opcode(n>>8), // little-endian
|
2019-12-03 14:05:06 +00:00
|
|
|
opcode.TOALTSTACK, opcode.DUPFROMALTSTACK,
|
2020-04-23 08:56:36 +00:00
|
|
|
opcode.JMPIF, 0x3, opcode.RET,
|
2019-12-03 14:05:06 +00:00
|
|
|
opcode.FROMALTSTACK, opcode.DEC,
|
2020-04-23 08:56:36 +00:00
|
|
|
opcode.CALL, 0xF9) // -7 -> JMP to TOALTSTACK)
|
2019-10-29 08:01:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestInvocationLimitGood(t *testing.T) {
|
|
|
|
prog := callNTimes(MaxInvocationStackSize - 1)
|
|
|
|
v := load(prog)
|
|
|
|
runVM(t, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInvocationLimitBad(t *testing.T) {
|
|
|
|
prog := callNTimes(MaxInvocationStackSize)
|
|
|
|
v := load(prog)
|
|
|
|
checkVMFailed(t, v)
|
|
|
|
}
|
|
|
|
|
2020-04-23 08:56:36 +00:00
|
|
|
func isLongJMP(op opcode.Opcode) bool {
|
|
|
|
return op == opcode.JMPL || op == opcode.JMPIFL || op == opcode.JMPIFNOTL ||
|
|
|
|
op == opcode.JMPEQL || op == opcode.JMPNEL ||
|
|
|
|
op == opcode.JMPGEL || op == opcode.JMPGTL ||
|
|
|
|
op == opcode.JMPLEL || op == opcode.JMPLTL
|
|
|
|
}
|
|
|
|
|
|
|
|
func getJMPProgram(op opcode.Opcode) []byte {
|
|
|
|
prog := []byte{byte(op)}
|
|
|
|
if isLongJMP(op) {
|
|
|
|
prog = append(prog, 0x07, 0x00, 0x00, 0x00)
|
|
|
|
} else {
|
|
|
|
prog = append(prog, 0x04)
|
|
|
|
}
|
|
|
|
return append(prog, byte(opcode.PUSH1), byte(opcode.RET), byte(opcode.PUSH2), byte(opcode.RET))
|
|
|
|
}
|
|
|
|
|
|
|
|
func testJMP(t *testing.T, op opcode.Opcode, res interface{}, items ...interface{}) {
|
|
|
|
prog := getJMPProgram(op)
|
|
|
|
v := load(prog)
|
|
|
|
for i := range items {
|
|
|
|
v.estack.PushVal(items[i])
|
|
|
|
}
|
|
|
|
if res == nil {
|
|
|
|
checkVMFailed(t, v)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
runVM(t, v)
|
|
|
|
require.EqualValues(t, res, v.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestJMPs(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
name string
|
|
|
|
items []interface{}
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "no condition",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "single item (true)",
|
|
|
|
items: []interface{}{true},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "single item (false)",
|
|
|
|
items: []interface{}{false},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "24 and 42",
|
|
|
|
items: []interface{}{24, 42},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "42 and 24",
|
|
|
|
items: []interface{}{42, 24},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "42 and 42",
|
|
|
|
items: []interface{}{42, 42},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2 is true, 1 is false
|
|
|
|
results := map[opcode.Opcode][]interface{}{
|
|
|
|
opcode.JMP: {2, 2, 2, 2, 2, 2},
|
|
|
|
opcode.JMPIF: {nil, 2, 1, 2, 2, 2},
|
|
|
|
opcode.JMPIFNOT: {nil, 1, 2, 1, 1, 1},
|
|
|
|
opcode.JMPEQ: {nil, nil, nil, 1, 1, 2},
|
|
|
|
opcode.JMPNE: {nil, nil, nil, 2, 2, 1},
|
|
|
|
opcode.JMPGE: {nil, nil, nil, 1, 2, 2},
|
|
|
|
opcode.JMPGT: {nil, nil, nil, 1, 2, 1},
|
|
|
|
opcode.JMPLE: {nil, nil, nil, 2, 1, 2},
|
|
|
|
opcode.JMPLT: {nil, nil, nil, 2, 1, 1},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tc := range testCases {
|
|
|
|
i := i
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
for op := opcode.JMP; op < opcode.JMPLEL; op++ {
|
|
|
|
resOp := op
|
|
|
|
if isLongJMP(op) {
|
|
|
|
resOp--
|
|
|
|
}
|
|
|
|
t.Run(op.String(), func(t *testing.T) {
|
|
|
|
testJMP(t, op, results[resOp][i], tc.items...)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-10 11:57:39 +00:00
|
|
|
func TestNOTNoArgument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NOT)
|
2019-09-10 11:57:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-10 11:57:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestNOTBool(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NOT)
|
2019-09-10 11:57:39 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(false)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:57:39 +00:00
|
|
|
assert.Equal(t, &BoolItem{true}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNOTNonZeroInt(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NOT)
|
2019-09-10 11:57:39 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(3)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:57:39 +00:00
|
|
|
assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNOTArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NOT)
|
2019-09-10 11:57:39 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:57:39 +00:00
|
|
|
assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNOTStruct(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NOT)
|
2019-09-10 11:57:39 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.Push(NewElement(&StructItem{[]StackItem{}}))
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:57:39 +00:00
|
|
|
assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNOTByteArray0(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NOT)
|
2019-09-10 11:57:39 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte{0, 0})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:57:39 +00:00
|
|
|
assert.Equal(t, &BoolItem{true}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNOTByteArray1(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NOT)
|
2019-09-10 11:57:39 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte{0, 1})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:57:39 +00:00
|
|
|
assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-11-07 09:14:36 +00:00
|
|
|
// getBigInt returns 2^a+b
|
|
|
|
func getBigInt(a, b int64) *big.Int {
|
|
|
|
p := new(big.Int).Exp(big.NewInt(2), big.NewInt(a), nil)
|
|
|
|
p.Add(p, big.NewInt(b))
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2018-03-30 16:15:06 +00:00
|
|
|
func TestAdd(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.ADD)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, int64(6), vm.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-11-07 09:14:36 +00:00
|
|
|
func TestADDBigResult(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.ADD)
|
2019-11-07 09:14:36 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits, -1))
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
2019-12-03 14:05:06 +00:00
|
|
|
func testBigArgument(t *testing.T, inst opcode.Opcode) {
|
2019-11-07 09:14:36 +00:00
|
|
|
prog := makeProgram(inst)
|
|
|
|
x := getBigInt(MaxBigIntegerSizeBits, 0)
|
|
|
|
t.Run(inst.String()+" big 1-st argument", func(t *testing.T) {
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(x)
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
})
|
|
|
|
t.Run(inst.String()+" big 2-nd argument", func(t *testing.T) {
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
vm.estack.PushVal(x)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestArithBigArgument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
testBigArgument(t, opcode.ADD)
|
|
|
|
testBigArgument(t, opcode.SUB)
|
|
|
|
testBigArgument(t, opcode.MUL)
|
|
|
|
testBigArgument(t, opcode.DIV)
|
|
|
|
testBigArgument(t, opcode.MOD)
|
2019-11-07 09:14:36 +00:00
|
|
|
}
|
|
|
|
|
2018-03-30 16:15:06 +00:00
|
|
|
func TestMul(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.MUL)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, int64(8), vm.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-11-07 09:14:36 +00:00
|
|
|
func TestMULBigResult(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.MUL)
|
2019-11-07 09:14:36 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits/2+1, 0))
|
|
|
|
vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits/2+1, 0))
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
2020-04-06 07:14:26 +00:00
|
|
|
func TestArithNegativeArguments(t *testing.T) {
|
2020-04-05 14:34:14 +00:00
|
|
|
runCase := func(op opcode.Opcode, p, q, result int64) func(t *testing.T) {
|
2020-03-17 12:45:53 +00:00
|
|
|
return func(t *testing.T) {
|
2020-04-05 14:34:14 +00:00
|
|
|
vm := load(makeProgram(op))
|
2020-03-17 12:45:53 +00:00
|
|
|
vm.estack.PushVal(p)
|
|
|
|
vm.estack.PushVal(q)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, result, vm.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-05 14:34:14 +00:00
|
|
|
t.Run("DIV", func(t *testing.T) {
|
|
|
|
t.Run("positive/positive", runCase(opcode.DIV, 5, 2, 2))
|
|
|
|
t.Run("positive/negative", runCase(opcode.DIV, 5, -2, -2))
|
|
|
|
t.Run("negative/positive", runCase(opcode.DIV, -5, 2, -2))
|
|
|
|
t.Run("negative/negative", runCase(opcode.DIV, -5, -2, 2))
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("MOD", func(t *testing.T) {
|
|
|
|
t.Run("positive/positive", runCase(opcode.MOD, 5, 2, 1))
|
|
|
|
t.Run("positive/negative", runCase(opcode.MOD, 5, -2, 1))
|
|
|
|
t.Run("negative/positive", runCase(opcode.MOD, -5, 2, -1))
|
|
|
|
t.Run("negative/negative", runCase(opcode.MOD, -5, -2, -1))
|
|
|
|
})
|
2020-03-17 12:45:53 +00:00
|
|
|
|
2020-04-06 07:14:26 +00:00
|
|
|
t.Run("SHR", func(t *testing.T) {
|
|
|
|
t.Run("positive/positive", runCase(opcode.SHR, 5, 2, 1))
|
|
|
|
t.Run("negative/positive", runCase(opcode.SHR, -5, 2, -2))
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("SHL", func(t *testing.T) {
|
|
|
|
t.Run("positive/positive", runCase(opcode.SHL, 5, 2, 20))
|
|
|
|
t.Run("negative/positive", runCase(opcode.SHL, -5, 2, -20))
|
|
|
|
})
|
2018-03-30 16:15:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSub(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUB)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, int64(2), vm.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-11-07 09:14:36 +00:00
|
|
|
func TestSUBBigResult(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUB)
|
2019-11-07 09:14:36 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits, -1))
|
|
|
|
vm.estack.PushVal(-1)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
2019-09-12 09:02:38 +00:00
|
|
|
func TestSHRGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SHR)
|
2019-09-12 09:02:38 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 09:02:38 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSHRZero(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SHR)
|
2019-09-12 09:02:38 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte{0, 1})
|
|
|
|
vm.estack.PushVal(0)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 09:02:38 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem([]byte{0, 1}), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2020-04-19 16:15:00 +00:00
|
|
|
func TestSHRNegative(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SHR)
|
2019-09-18 11:35:29 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(5)
|
2020-04-19 16:15:00 +00:00
|
|
|
vm.estack.PushVal(-1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-18 11:35:29 +00:00
|
|
|
}
|
|
|
|
|
2019-11-07 09:14:36 +00:00
|
|
|
func TestSHRBigArgument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SHR)
|
2019-11-07 09:14:36 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits, 0))
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
2019-09-12 09:02:38 +00:00
|
|
|
func TestSHLGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SHL)
|
2019-09-12 09:02:38 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 09:02:38 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(16), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSHLZero(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SHL)
|
2019-09-12 09:02:38 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte{0, 1})
|
|
|
|
vm.estack.PushVal(0)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 09:02:38 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem([]byte{0, 1}), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-09-18 11:35:29 +00:00
|
|
|
func TestSHLBigValue(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SHL)
|
2019-09-18 11:35:29 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(5)
|
2019-11-07 09:50:11 +00:00
|
|
|
vm.estack.PushVal(maxSHLArg + 1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-18 11:35:29 +00:00
|
|
|
}
|
|
|
|
|
2019-11-07 09:14:36 +00:00
|
|
|
func TestSHLBigResult(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SHL)
|
2019-11-07 09:14:36 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits/2, 0))
|
|
|
|
vm.estack.PushVal(MaxBigIntegerSizeBits / 2)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSHLBigArgument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SHR)
|
2019-11-07 09:14:36 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits, 0))
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
2018-03-30 16:15:06 +00:00
|
|
|
func TestLT(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.LT)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(3)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLTE(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.LTE)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(3)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGT(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.GT)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(9)
|
|
|
|
vm.estack.PushVal(3)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGTE(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.GTE)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(3)
|
|
|
|
vm.estack.PushVal(3)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDepth(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.DEPTH)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(3)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, int64(3), vm.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-09-12 07:50:43 +00:00
|
|
|
func TestEQUALNoArguments(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.EQUAL)
|
2019-09-12 07:50:43 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-12 07:50:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEQUALBad1Argument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.EQUAL)
|
2019-09-12 07:50:43 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-12 07:50:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEQUALGoodInteger(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.EQUAL)
|
2019-09-12 07:50:43 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(5)
|
|
|
|
vm.estack.PushVal(5)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 07:50:43 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BoolItem{true}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2020-03-11 13:44:10 +00:00
|
|
|
func TestEQUALIntegerByteArray(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.EQUAL)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte{16})
|
|
|
|
vm.estack.PushVal(16)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BoolItem{true}, vm.estack.Pop().value)
|
2019-09-12 07:50:43 +00:00
|
|
|
}
|
|
|
|
|
2019-09-18 11:10:10 +00:00
|
|
|
func TestEQUALArrayTrue(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.DUP, opcode.EQUAL)
|
2019-09-18 11:10:10 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-18 11:10:10 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BoolItem{true}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEQUALArrayFalse(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.EQUAL)
|
2019-09-18 11:10:10 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{})
|
|
|
|
vm.estack.PushVal([]StackItem{})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-18 11:10:10 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-09-24 13:45:41 +00:00
|
|
|
func TestEQUALMapTrue(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.DUP, opcode.EQUAL)
|
2019-09-24 13:45:41 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.Push(&Element{value: NewMapItem()})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 13:45:41 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BoolItem{true}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEQUALMapFalse(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.EQUAL)
|
2019-09-24 13:45:41 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.Push(&Element{value: NewMapItem()})
|
|
|
|
vm.estack.Push(&Element{value: NewMapItem()})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 13:45:41 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2018-03-30 16:15:06 +00:00
|
|
|
func TestNumEqual(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NUMEQUAL)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNumNotEqual(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NUMNOTEQUAL)
|
2018-03-30 16:15:06 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
|
|
|
}
|
|
|
|
|
2018-04-02 15:04:42 +00:00
|
|
|
func TestINC(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.INC)
|
2018-04-02 15:04:42 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-04-02 15:04:42 +00:00
|
|
|
assert.Equal(t, big.NewInt(2), vm.estack.Pop().BigInt())
|
|
|
|
}
|
|
|
|
|
2019-11-07 09:14:36 +00:00
|
|
|
func TestINCBigResult(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.INC, opcode.INC)
|
2019-11-07 09:14:36 +00:00
|
|
|
vm := load(prog)
|
|
|
|
x := getBigInt(MaxBigIntegerSizeBits, -2)
|
|
|
|
vm.estack.PushVal(x)
|
|
|
|
|
|
|
|
require.NoError(t, vm.Step())
|
|
|
|
require.False(t, vm.HasFailed())
|
|
|
|
require.Equal(t, 1, vm.estack.Len())
|
|
|
|
require.Equal(t, new(big.Int).Add(x, big.NewInt(1)), vm.estack.Top().BigInt())
|
|
|
|
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDECBigResult(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.DEC, opcode.DEC)
|
2019-11-07 09:14:36 +00:00
|
|
|
vm := load(prog)
|
|
|
|
x := getBigInt(MaxBigIntegerSizeBits, -2)
|
|
|
|
x.Neg(x)
|
|
|
|
vm.estack.PushVal(x)
|
|
|
|
|
|
|
|
require.NoError(t, vm.Step())
|
|
|
|
require.False(t, vm.HasFailed())
|
|
|
|
require.Equal(t, 1, vm.estack.Len())
|
|
|
|
require.Equal(t, new(big.Int).Sub(x, big.NewInt(1)), vm.estack.Top().BigInt())
|
|
|
|
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
2020-04-24 09:31:59 +00:00
|
|
|
func TestNEWARRAY0(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.NEWARRAY0)
|
|
|
|
v := load(prog)
|
|
|
|
runVM(t, v)
|
|
|
|
require.Equal(t, 1, v.estack.Len())
|
|
|
|
require.Equal(t, &ArrayItem{[]StackItem{}}, v.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNEWSTRUCT0(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.NEWSTRUCT0)
|
|
|
|
v := load(prog)
|
|
|
|
runVM(t, v)
|
|
|
|
require.Equal(t, 1, v.estack.Len())
|
|
|
|
require.Equal(t, &StructItem{[]StackItem{}}, v.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-09-06 16:00:04 +00:00
|
|
|
func TestNEWARRAYInteger(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWARRAY)
|
2019-09-06 16:00:04 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 16:00:04 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
2019-09-12 08:24:10 +00:00
|
|
|
assert.Equal(t, &ArrayItem{[]StackItem{makeStackItem(false)}}, vm.estack.Pop().value)
|
2019-09-06 16:00:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestNEWARRAYStruct(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWARRAY)
|
2019-09-06 16:00:04 +00:00
|
|
|
vm := load(prog)
|
|
|
|
arr := []StackItem{makeStackItem(42)}
|
|
|
|
vm.estack.Push(&Element{value: &StructItem{arr}})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 16:00:04 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-12-03 14:05:06 +00:00
|
|
|
func testNEWARRAYIssue437(t *testing.T, i1, i2 opcode.Opcode, appended bool) {
|
2019-10-18 10:01:51 +00:00
|
|
|
prog := makeProgram(
|
2019-12-03 14:05:06 +00:00
|
|
|
opcode.PUSH2, i1,
|
|
|
|
opcode.DUP, opcode.PUSH3, opcode.APPEND,
|
|
|
|
opcode.TOALTSTACK, opcode.DUPFROMALTSTACK, i2,
|
|
|
|
opcode.DUP, opcode.PUSH4, opcode.APPEND,
|
|
|
|
opcode.FROMALTSTACK, opcode.PUSH5, opcode.APPEND)
|
2019-10-18 10:01:51 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.Run()
|
|
|
|
|
2020-04-24 10:48:19 +00:00
|
|
|
arr := makeArrayOfType(4, BooleanT)
|
2019-10-18 10:01:51 +00:00
|
|
|
arr[2] = makeStackItem(3)
|
|
|
|
arr[3] = makeStackItem(4)
|
|
|
|
if appended {
|
|
|
|
arr = append(arr, makeStackItem(5))
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.Equal(t, false, vm.HasFailed())
|
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
2019-12-03 14:05:06 +00:00
|
|
|
if i2 == opcode.NEWARRAY {
|
2019-10-18 10:01:51 +00:00
|
|
|
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
|
|
|
|
} else {
|
|
|
|
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNEWARRAYIssue437(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
t.Run("Array+Array", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWARRAY, opcode.NEWARRAY, true) })
|
|
|
|
t.Run("Struct+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWSTRUCT, opcode.NEWSTRUCT, true) })
|
|
|
|
t.Run("Array+Struct", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWARRAY, opcode.NEWSTRUCT, false) })
|
|
|
|
t.Run("Struct+Array", func(t *testing.T) { testNEWARRAYIssue437(t, opcode.NEWSTRUCT, opcode.NEWARRAY, false) })
|
2019-10-18 10:01:51 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 16:00:04 +00:00
|
|
|
func TestNEWARRAYArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWARRAY)
|
2019-09-06 16:00:04 +00:00
|
|
|
vm := load(prog)
|
|
|
|
arr := []StackItem{makeStackItem(42)}
|
|
|
|
vm.estack.Push(&Element{value: &ArrayItem{arr}})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 16:00:04 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-09-12 08:48:39 +00:00
|
|
|
func TestNEWARRAYByteArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWARRAY)
|
2019-09-06 16:00:04 +00:00
|
|
|
vm := load(prog)
|
2019-09-12 08:48:39 +00:00
|
|
|
vm.estack.PushVal([]byte{})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 08:48:39 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &ArrayItem{[]StackItem{}}, vm.estack.Pop().value)
|
2019-09-06 16:00:04 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 10:48:19 +00:00
|
|
|
func testNEWARRAYT(t *testing.T, typ StackItemType, item StackItem) {
|
|
|
|
prog := makeProgram(opcode.NEWARRAYT, opcode.Opcode(typ), opcode.PUSH0, opcode.PICKITEM)
|
|
|
|
v := load(prog)
|
|
|
|
v.estack.PushVal(1)
|
|
|
|
if item == nil {
|
|
|
|
checkVMFailed(t, v)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
runVM(t, v)
|
|
|
|
require.Equal(t, 1, v.estack.Len())
|
|
|
|
require.Equal(t, item, v.estack.Pop().Item())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNEWARRAYT(t *testing.T) {
|
|
|
|
testCases := map[StackItemType]StackItem{
|
|
|
|
BooleanT: NewBoolItem(false),
|
|
|
|
IntegerT: NewBigIntegerItem(big.NewInt(0)),
|
|
|
|
ByteArrayT: NewByteArrayItem([]byte{}),
|
|
|
|
ArrayT: NullItem{},
|
|
|
|
0xFF: nil,
|
|
|
|
}
|
|
|
|
for typ, item := range testCases {
|
|
|
|
t.Run(typ.String(), func(t *testing.T) { testNEWARRAYT(t, typ, item) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-17 08:03:21 +00:00
|
|
|
func TestNEWARRAYBadSize(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWARRAY)
|
2019-10-17 08:03:21 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(MaxArraySize + 1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-10-17 08:03:21 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 16:00:04 +00:00
|
|
|
func TestNEWSTRUCTInteger(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWSTRUCT)
|
2019-09-06 16:00:04 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 16:00:04 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
2019-09-12 08:24:10 +00:00
|
|
|
assert.Equal(t, &StructItem{[]StackItem{makeStackItem(false)}}, vm.estack.Pop().value)
|
2019-09-06 16:00:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestNEWSTRUCTArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWSTRUCT)
|
2019-09-06 16:00:04 +00:00
|
|
|
vm := load(prog)
|
|
|
|
arr := []StackItem{makeStackItem(42)}
|
|
|
|
vm.estack.Push(&Element{value: &ArrayItem{arr}})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 16:00:04 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNEWSTRUCTStruct(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWSTRUCT)
|
2019-09-06 16:00:04 +00:00
|
|
|
vm := load(prog)
|
|
|
|
arr := []StackItem{makeStackItem(42)}
|
|
|
|
vm.estack.Push(&Element{value: &StructItem{arr}})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 16:00:04 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-09-12 08:48:39 +00:00
|
|
|
func TestNEWSTRUCTByteArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWSTRUCT)
|
2019-09-06 16:00:04 +00:00
|
|
|
vm := load(prog)
|
2019-09-12 08:48:39 +00:00
|
|
|
vm.estack.PushVal([]byte{})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 08:48:39 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &StructItem{[]StackItem{}}, vm.estack.Pop().value)
|
2019-09-06 16:00:04 +00:00
|
|
|
}
|
|
|
|
|
2019-10-17 08:03:21 +00:00
|
|
|
func TestNEWSTRUCTBadSize(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWSTRUCT)
|
2019-10-17 08:03:21 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(MaxArraySize + 1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-10-17 08:03:21 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 14:05:56 +00:00
|
|
|
func TestAPPENDArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.DUP, opcode.PUSH5, opcode.APPEND)
|
2019-09-11 14:05:56 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.Push(&Element{value: &ArrayItem{}})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-11 14:05:56 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &ArrayItem{[]StackItem{makeStackItem(5)}}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAPPENDStruct(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.DUP, opcode.PUSH5, opcode.APPEND)
|
2019-09-11 14:05:56 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.Push(&Element{value: &StructItem{}})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-11 14:05:56 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &StructItem{[]StackItem{makeStackItem(5)}}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-09-18 11:03:15 +00:00
|
|
|
func TestAPPENDCloneStruct(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.DUP, opcode.PUSH0, opcode.NEWSTRUCT, opcode.TOALTSTACK,
|
|
|
|
opcode.DUPFROMALTSTACK, opcode.APPEND, opcode.FROMALTSTACK, opcode.PUSH1, opcode.APPEND)
|
2019-09-18 11:03:15 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.Push(&Element{value: &ArrayItem{}})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-18 11:03:15 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &ArrayItem{[]StackItem{
|
|
|
|
&StructItem{[]StackItem{}},
|
|
|
|
}}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-09-11 14:05:56 +00:00
|
|
|
func TestAPPENDBadNoArguments(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.APPEND)
|
2019-09-11 14:05:56 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 14:05:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestAPPENDBad1Argument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.APPEND)
|
2019-09-11 14:05:56 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 14:05:56 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 14:08:36 +00:00
|
|
|
func TestAPPENDWrongType(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.APPEND)
|
2019-09-11 14:08:36 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte{})
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 14:08:36 +00:00
|
|
|
}
|
|
|
|
|
2019-10-17 08:03:35 +00:00
|
|
|
func TestAPPENDGoodSizeLimit(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWARRAY, opcode.DUP, opcode.PUSH0, opcode.APPEND)
|
2019-10-17 08:03:35 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(MaxArraySize - 1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-10-17 08:03:35 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, MaxArraySize, len(vm.estack.Pop().Array()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAPPENDBadSizeLimit(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NEWARRAY, opcode.DUP, opcode.PUSH0, opcode.APPEND)
|
2019-10-17 08:03:35 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(MaxArraySize)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-10-17 08:03:35 +00:00
|
|
|
}
|
|
|
|
|
2019-09-12 08:19:25 +00:00
|
|
|
func TestPICKITEMBadIndex(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PICKITEM)
|
2019-09-12 08:19:25 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{})
|
|
|
|
vm.estack.PushVal(0)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-12 08:19:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestPICKITEMArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PICKITEM)
|
2019-09-12 08:19:25 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{makeStackItem(1), makeStackItem(2)})
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 08:19:25 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPICKITEMByteArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PICKITEM)
|
2019-09-12 08:19:25 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte{1, 2})
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 08:19:25 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-12-17 14:20:44 +00:00
|
|
|
func TestPICKITEMDupArray(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.DUP, opcode.PUSH0, opcode.PICKITEM, opcode.ABS)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{makeStackItem(-1)})
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Pop().BigInt().Int64())
|
|
|
|
items := vm.estack.Pop().Value().([]StackItem)
|
|
|
|
assert.Equal(t, big.NewInt(-1), items[0].Value())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPICKITEMDupMap(t *testing.T) {
|
2020-04-21 13:45:48 +00:00
|
|
|
prog := makeProgram(opcode.DUP, opcode.PUSHINT8, 42, opcode.PICKITEM, opcode.ABS)
|
2019-12-17 14:20:44 +00:00
|
|
|
vm := load(prog)
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(makeStackItem([]byte{42}), makeStackItem(-1))
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Pop().BigInt().Int64())
|
2020-03-31 10:30:38 +00:00
|
|
|
items := vm.estack.Pop().Value().([]MapElement)
|
|
|
|
assert.Equal(t, 1, len(items))
|
|
|
|
assert.Equal(t, []byte{42}, items[0].Key.Value())
|
|
|
|
assert.Equal(t, big.NewInt(-1), items[0].Value.Value())
|
2019-12-17 14:20:44 +00:00
|
|
|
}
|
|
|
|
|
2019-09-24 12:58:31 +00:00
|
|
|
func TestPICKITEMMap(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PICKITEM)
|
2019-09-24 12:58:31 +00:00
|
|
|
vm := load(prog)
|
|
|
|
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(makeStackItem(5), makeStackItem(3))
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
vm.estack.PushVal(makeStackItem(5))
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:58:31 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(3), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSETITEMMap(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SETITEM, opcode.PICKITEM)
|
2019-09-24 12:58:31 +00:00
|
|
|
vm := load(prog)
|
|
|
|
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(makeStackItem(5), makeStackItem(3))
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
vm.estack.PushVal(5)
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
vm.estack.PushVal(5)
|
|
|
|
vm.estack.PushVal([]byte{0, 1})
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:58:31 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem([]byte{0, 1}), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-10-17 08:18:15 +00:00
|
|
|
func TestSETITEMBigMapBad(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SETITEM)
|
2019-10-17 08:18:15 +00:00
|
|
|
vm := load(prog)
|
|
|
|
|
|
|
|
m := NewMapItem()
|
|
|
|
for i := 0; i < MaxArraySize; i++ {
|
|
|
|
m.Add(makeStackItem(i), makeStackItem(i))
|
|
|
|
}
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
vm.estack.PushVal(MaxArraySize)
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-10-17 08:18:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSETITEMBigMapGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SETITEM)
|
2019-10-17 08:18:15 +00:00
|
|
|
vm := load(prog)
|
|
|
|
|
|
|
|
m := NewMapItem()
|
|
|
|
for i := 0; i < MaxArraySize; i++ {
|
|
|
|
m.Add(makeStackItem(i), makeStackItem(i))
|
|
|
|
}
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-10-17 08:18:15 +00:00
|
|
|
}
|
|
|
|
|
2019-09-12 08:53:11 +00:00
|
|
|
func TestSIZENoArgument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SIZE)
|
2019-09-12 08:53:11 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-12 08:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSIZEByteArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SIZE)
|
2019-09-12 08:53:11 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte{0, 1})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 08:53:11 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSIZEBool(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SIZE)
|
2019-09-12 08:53:11 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(false)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 08:53:11 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
2020-04-15 13:19:42 +00:00
|
|
|
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
2019-09-12 08:53:11 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 09:24:08 +00:00
|
|
|
func TestSIZEArray(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.SIZE)
|
2019-09-24 13:50:37 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{
|
|
|
|
makeStackItem(1),
|
|
|
|
makeStackItem([]byte{}),
|
|
|
|
})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 13:50:37 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2020-04-24 09:24:08 +00:00
|
|
|
func TestSIZEMap(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.SIZE)
|
2019-09-24 13:50:37 +00:00
|
|
|
vm := load(prog)
|
|
|
|
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(makeStackItem(5), makeStackItem(6))
|
|
|
|
m.Add(makeStackItem([]byte{0, 1}), makeStackItem(6))
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 13:50:37 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-09-24 12:41:39 +00:00
|
|
|
func TestKEYSMap(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.KEYS)
|
2019-09-24 12:41:39 +00:00
|
|
|
vm := load(prog)
|
|
|
|
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(makeStackItem(5), makeStackItem(6))
|
|
|
|
m.Add(makeStackItem([]byte{0, 1}), makeStackItem(6))
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:41:39 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
|
|
|
|
top := vm.estack.Pop().value.(*ArrayItem)
|
|
|
|
assert.Equal(t, 2, len(top.value))
|
|
|
|
assert.Contains(t, top.value, makeStackItem(5))
|
|
|
|
assert.Contains(t, top.value, makeStackItem([]byte{0, 1}))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestKEYSNoArgument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.KEYS)
|
2019-09-24 12:41:39 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-24 12:41:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestKEYSWrongType(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.KEYS)
|
2019-09-24 12:41:39 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{})
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-24 12:41:39 +00:00
|
|
|
}
|
|
|
|
|
2019-09-24 12:53:55 +00:00
|
|
|
func TestVALUESMap(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.VALUES)
|
2019-09-24 12:53:55 +00:00
|
|
|
vm := load(prog)
|
|
|
|
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(makeStackItem(5), makeStackItem([]byte{2, 3}))
|
|
|
|
m.Add(makeStackItem([]byte{0, 1}), makeStackItem([]StackItem{}))
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:53:55 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
|
|
|
|
top := vm.estack.Pop().value.(*ArrayItem)
|
|
|
|
assert.Equal(t, 2, len(top.value))
|
|
|
|
assert.Contains(t, top.value, makeStackItem([]byte{2, 3}))
|
|
|
|
assert.Contains(t, top.value, makeStackItem([]StackItem{}))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestVALUESArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.VALUES)
|
2019-09-24 12:53:55 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{makeStackItem(4)})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:53:55 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &ArrayItem{[]StackItem{makeStackItem(4)}}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestVALUESNoArgument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.VALUES)
|
2019-09-24 12:53:55 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-24 12:53:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestVALUESWrongType(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.VALUES)
|
2019-09-24 12:53:55 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(5)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-24 12:53:55 +00:00
|
|
|
}
|
|
|
|
|
2019-09-24 12:25:57 +00:00
|
|
|
func TestHASKEYArrayTrue(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PUSH5, opcode.NEWARRAY, opcode.PUSH4, opcode.HASKEY)
|
2019-09-24 12:25:57 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:25:57 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(true), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHASKEYArrayFalse(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PUSH5, opcode.NEWARRAY, opcode.PUSH5, opcode.HASKEY)
|
2019-09-24 12:25:57 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:25:57 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(false), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHASKEYStructTrue(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PUSH5, opcode.NEWSTRUCT, opcode.PUSH4, opcode.HASKEY)
|
2019-09-24 12:25:57 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:25:57 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(true), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHASKEYStructFalse(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PUSH5, opcode.NEWSTRUCT, opcode.PUSH5, opcode.HASKEY)
|
2019-09-24 12:25:57 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:25:57 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(false), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHASKEYMapTrue(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.HASKEY)
|
2019-09-24 12:25:57 +00:00
|
|
|
vm := load(prog)
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(makeStackItem(5), makeStackItem(6))
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
vm.estack.PushVal(5)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:25:57 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(true), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHASKEYMapFalse(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.HASKEY)
|
2019-09-24 12:25:57 +00:00
|
|
|
vm := load(prog)
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(makeStackItem(5), makeStackItem(6))
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
vm.estack.PushVal(6)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 12:25:57 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(false), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHASKEYNoArguments(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.HASKEY)
|
2019-09-24 12:25:57 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-24 12:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestHASKEY1Argument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.HASKEY)
|
2019-09-24 12:25:57 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-24 12:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestHASKEYWrongKeyType(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.HASKEY)
|
2019-09-24 12:25:57 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{})
|
|
|
|
vm.estack.PushVal([]StackItem{})
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-24 12:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestHASKEYWrongCollectionType(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.HASKEY)
|
2019-09-24 12:25:57 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-24 12:25:57 +00:00
|
|
|
}
|
|
|
|
|
2019-09-10 11:19:52 +00:00
|
|
|
func TestSIGNNoArgument(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SIGN)
|
2019-09-10 11:19:52 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-10 11:19:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSIGNWrongType(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SIGN)
|
2019-09-10 11:19:52 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]StackItem{})
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-10 11:19:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSIGNBool(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SIGN)
|
2019-09-10 11:19:52 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(false)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:19:52 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BigIntegerItem{big.NewInt(0)}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSIGNPositiveInt(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SIGN)
|
2019-09-10 11:19:52 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:19:52 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BigIntegerItem{big.NewInt(1)}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSIGNNegativeInt(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SIGN)
|
2019-09-10 11:19:52 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(-1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:19:52 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BigIntegerItem{big.NewInt(-1)}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSIGNZero(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SIGN)
|
2019-09-10 11:19:52 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:19:52 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BigIntegerItem{big.NewInt(0)}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSIGNByteArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SIGN)
|
2019-09-10 11:19:52 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte{0, 1})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 11:19:52 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &BigIntegerItem{big.NewInt(1)}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2018-03-30 16:15:06 +00:00
|
|
|
func TestAppCall(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := []byte{byte(opcode.APPCALL)}
|
2020-03-10 14:17:36 +00:00
|
|
|
hash := util.Uint160{1, 2}
|
2019-11-27 09:20:31 +00:00
|
|
|
prog = append(prog, hash.BytesBE()...)
|
2019-12-03 14:05:06 +00:00
|
|
|
prog = append(prog, byte(opcode.RET))
|
2018-03-30 16:15:06 +00:00
|
|
|
|
|
|
|
vm := load(prog)
|
2020-03-10 14:17:36 +00:00
|
|
|
vm.SetScriptGetter(func(in util.Uint160) ([]byte, bool) {
|
2019-09-30 16:52:16 +00:00
|
|
|
if in.Equals(hash) {
|
2020-03-10 14:17:36 +00:00
|
|
|
return makeProgram(opcode.DEPTH), true
|
2019-09-30 16:52:16 +00:00
|
|
|
}
|
2020-03-10 14:17:36 +00:00
|
|
|
return nil, false
|
2019-09-30 16:52:16 +00:00
|
|
|
})
|
2018-03-30 16:15:06 +00:00
|
|
|
vm.estack.PushVal(2)
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
elem := vm.estack.Pop() // depth should be 1
|
|
|
|
assert.Equal(t, int64(1), elem.BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2020-03-10 14:17:36 +00:00
|
|
|
func TestAppCallDynamicBad(t *testing.T) {
|
|
|
|
prog := []byte{byte(opcode.APPCALL)}
|
|
|
|
hash := util.Uint160{}
|
|
|
|
prog = append(prog, hash.BytesBE()...)
|
|
|
|
prog = append(prog, byte(opcode.RET))
|
|
|
|
|
|
|
|
vm := load(prog)
|
|
|
|
vm.SetScriptGetter(func(in util.Uint160) ([]byte, bool) {
|
|
|
|
if in.Equals(hash) {
|
|
|
|
return makeProgram(opcode.DEPTH), true
|
|
|
|
}
|
|
|
|
return nil, false
|
|
|
|
})
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(hash.BytesBE())
|
|
|
|
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAppCallDynamicGood(t *testing.T) {
|
|
|
|
prog := []byte{byte(opcode.APPCALL)}
|
|
|
|
zeroHash := util.Uint160{}
|
|
|
|
hash := util.Uint160{1, 2, 3}
|
|
|
|
prog = append(prog, zeroHash.BytesBE()...)
|
|
|
|
prog = append(prog, byte(opcode.RET))
|
|
|
|
|
|
|
|
vm := load(prog)
|
|
|
|
vm.SetScriptGetter(func(in util.Uint160) ([]byte, bool) {
|
|
|
|
if in.Equals(hash) {
|
|
|
|
return makeProgram(opcode.DEPTH), true
|
|
|
|
}
|
|
|
|
return nil, false
|
|
|
|
})
|
|
|
|
vm.estack.PushVal(42)
|
|
|
|
vm.estack.PushVal(42)
|
|
|
|
vm.estack.PushVal(hash.BytesBE())
|
|
|
|
vm.Context().hasDynamicInvoke = true
|
|
|
|
|
|
|
|
runVM(t, vm)
|
|
|
|
elem := vm.estack.Pop() // depth should be 2
|
|
|
|
assert.Equal(t, int64(2), elem.BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2018-03-30 16:15:06 +00:00
|
|
|
func TestSimpleCall(t *testing.T) {
|
2020-04-21 13:56:58 +00:00
|
|
|
buf := io.NewBufBinWriter()
|
|
|
|
w := buf.BinWriter
|
|
|
|
emit.Opcode(w, opcode.PUSH2)
|
2020-04-23 08:56:36 +00:00
|
|
|
emit.Instruction(w, opcode.CALL, []byte{03})
|
2020-04-21 13:56:58 +00:00
|
|
|
emit.Opcode(w, opcode.RET)
|
|
|
|
emit.Opcode(w, opcode.PUSH10)
|
|
|
|
emit.Opcode(w, opcode.ADD)
|
|
|
|
emit.Opcode(w, opcode.RET)
|
2018-03-30 16:15:06 +00:00
|
|
|
|
2020-04-21 13:56:58 +00:00
|
|
|
result := 12
|
|
|
|
vm := load(buf.Bytes())
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2018-03-30 16:15:06 +00:00
|
|
|
assert.Equal(t, result, int(vm.estack.Pop().BigInt().Int64()))
|
|
|
|
}
|
|
|
|
|
2019-09-05 12:05:44 +00:00
|
|
|
func TestNZtrue(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NZ)
|
2019-09-05 12:05:44 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 12:05:44 +00:00
|
|
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNZfalse(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NZ)
|
2019-09-05 12:05:44 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 12:05:44 +00:00
|
|
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
|
|
|
}
|
|
|
|
|
2019-09-05 12:18:04 +00:00
|
|
|
func TestPICKbadNoitem(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PICK)
|
2019-09-05 12:18:04 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 12:18:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestPICKbadNegative(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PICK)
|
2019-09-05 12:18:04 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(-1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 12:18:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestPICKgood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PICK)
|
2019-09-05 12:18:04 +00:00
|
|
|
result := 2
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(result)
|
|
|
|
vm.estack.PushVal(3)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(5)
|
|
|
|
vm.estack.PushVal(3)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 12:18:04 +00:00
|
|
|
assert.Equal(t, int64(result), vm.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-12-17 13:56:58 +00:00
|
|
|
func TestPICKDup(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.PUSHM1, opcode.PUSH0,
|
|
|
|
opcode.PUSH1,
|
|
|
|
opcode.PUSH2,
|
|
|
|
opcode.PICK,
|
|
|
|
opcode.ABS)
|
|
|
|
vm := load(prog)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 4, vm.estack.Len())
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Pop().BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Pop().BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(0), vm.estack.Pop().BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(-1), vm.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-09-12 07:57:55 +00:00
|
|
|
func TestROTBad(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.ROT)
|
2019-09-12 07:57:55 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-12 07:57:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestROTGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.ROT)
|
2019-09-12 07:57:55 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(3)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 07:57:55 +00:00
|
|
|
assert.Equal(t, 3, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
|
|
|
assert.Equal(t, makeStackItem(3), vm.estack.Pop().value)
|
|
|
|
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
2019-12-16 16:53:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestROLLBad1(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.ROLL)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(-1)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestROLLBad2(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.ROLL)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(3)
|
|
|
|
vm.estack.PushVal(3)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestROLLGood(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.ROLL)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(3)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 4, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(3), vm.estack.Pop().value)
|
|
|
|
assert.Equal(t, makeStackItem(4), vm.estack.Pop().value)
|
|
|
|
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
|
|
|
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
2019-09-12 07:57:55 +00:00
|
|
|
}
|
|
|
|
|
2019-09-05 12:43:59 +00:00
|
|
|
func TestXTUCKbadNoitem(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.XTUCK)
|
2019-09-05 12:43:59 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 12:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestXTUCKbadNoN(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.XTUCK)
|
2019-09-05 12:43:59 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 12:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestXTUCKbadNegative(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.XTUCK)
|
2019-09-05 12:43:59 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(-1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 12:43:59 +00:00
|
|
|
}
|
|
|
|
|
2019-09-12 07:39:54 +00:00
|
|
|
func TestXTUCKbadZero(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.XTUCK)
|
2019-09-12 07:39:54 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(0)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-12 07:39:54 +00:00
|
|
|
}
|
|
|
|
|
2019-09-05 12:43:59 +00:00
|
|
|
func TestXTUCKgood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.XTUCK)
|
2019-09-05 12:43:59 +00:00
|
|
|
topelement := 5
|
|
|
|
xtuckdepth := 3
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(3)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(topelement)
|
|
|
|
vm.estack.PushVal(xtuckdepth)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 12:43:59 +00:00
|
|
|
assert.Equal(t, int64(topelement), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(topelement), vm.estack.Peek(xtuckdepth).BigInt().Int64())
|
|
|
|
}
|
2019-09-05 12:18:04 +00:00
|
|
|
|
2019-09-05 13:34:35 +00:00
|
|
|
func TestTUCKbadNoitems(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.TUCK)
|
2019-09-05 13:34:35 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 13:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTUCKbadNoitem(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.TUCK)
|
2019-09-05 13:34:35 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 13:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTUCKgood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.TUCK)
|
2019-09-05 13:34:35 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(42)
|
|
|
|
vm.estack.PushVal(34)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 13:34:35 +00:00
|
|
|
assert.Equal(t, int64(34), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(42), vm.estack.Peek(1).BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(34), vm.estack.Peek(2).BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTUCKgood2(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.TUCK)
|
2019-09-05 13:34:35 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(11)
|
|
|
|
vm.estack.PushVal(42)
|
|
|
|
vm.estack.PushVal(34)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 13:34:35 +00:00
|
|
|
assert.Equal(t, int64(34), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(42), vm.estack.Peek(1).BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(34), vm.estack.Peek(2).BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(11), vm.estack.Peek(3).BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-09-05 12:57:44 +00:00
|
|
|
func TestOVERbadNoitem(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.OVER)
|
2019-09-05 12:57:44 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-18 11:24:42 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
2019-09-05 12:57:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestOVERbadNoitems(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.OVER)
|
2019-09-05 12:57:44 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 12:57:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestOVERgood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.OVER)
|
2019-09-05 12:57:44 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(42)
|
|
|
|
vm.estack.PushVal(34)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 12:57:44 +00:00
|
|
|
assert.Equal(t, int64(42), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(34), vm.estack.Peek(1).BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(42), vm.estack.Peek(2).BigInt().Int64())
|
|
|
|
assert.Equal(t, 3, vm.estack.Len())
|
|
|
|
}
|
|
|
|
|
2019-12-17 13:56:58 +00:00
|
|
|
func TestOVERDup(t *testing.T) {
|
2020-04-21 13:45:48 +00:00
|
|
|
prog := makeProgram(opcode.PUSHDATA1, 2, 1, 0,
|
2019-12-17 13:56:58 +00:00
|
|
|
opcode.PUSH1,
|
|
|
|
opcode.OVER,
|
|
|
|
opcode.PUSH1,
|
|
|
|
opcode.LEFT,
|
2020-04-21 13:45:48 +00:00
|
|
|
opcode.PUSHDATA1, 1, 2,
|
2019-12-17 13:56:58 +00:00
|
|
|
opcode.CAT)
|
|
|
|
vm := load(prog)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 3, vm.estack.Len())
|
|
|
|
assert.Equal(t, []byte{0x01, 0x02}, vm.estack.Pop().Bytes())
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Pop().BigInt().Int64())
|
|
|
|
assert.Equal(t, []byte{0x01, 0x00}, vm.estack.Pop().Bytes())
|
|
|
|
}
|
|
|
|
|
2019-09-12 08:09:23 +00:00
|
|
|
func TestNIPBadNoItem(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NIP)
|
2019-09-12 08:09:23 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-12 08:09:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestNIPGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.NIP)
|
2019-09-12 08:09:23 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 08:09:23 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-09-12 08:05:10 +00:00
|
|
|
func TestDROPBadNoItem(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.DROP)
|
2019-09-12 08:05:10 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-12 08:05:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDROPGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.DROP)
|
2019-09-12 08:05:10 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 08:05:10 +00:00
|
|
|
assert.Equal(t, 0, vm.estack.Len())
|
|
|
|
}
|
|
|
|
|
2019-09-05 13:42:54 +00:00
|
|
|
func TestXDROPbadNoitem(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.XDROP)
|
2019-09-05 13:42:54 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 13:42:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestXDROPbadNoN(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.XDROP)
|
2019-09-05 13:42:54 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 13:42:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestXDROPbadNegative(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.XDROP)
|
2019-09-05 13:42:54 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(-1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 13:42:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestXDROPgood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.XDROP)
|
2019-09-05 13:42:54 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 13:42:54 +00:00
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
assert.Equal(t, int64(2), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Peek(1).BigInt().Int64())
|
|
|
|
}
|
2019-09-05 12:57:44 +00:00
|
|
|
|
2019-09-05 14:20:53 +00:00
|
|
|
func TestINVERTbadNoitem(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.INVERT)
|
2019-09-05 14:20:53 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-05 14:20:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestINVERTgood1(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.INVERT)
|
2019-09-05 14:20:53 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 14:20:53 +00:00
|
|
|
assert.Equal(t, int64(-1), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestINVERTgood2(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.INVERT)
|
2019-09-05 14:20:53 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(-1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 14:20:53 +00:00
|
|
|
assert.Equal(t, int64(0), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestINVERTgood3(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.INVERT)
|
2019-09-05 14:20:53 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0x69)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-05 14:20:53 +00:00
|
|
|
assert.Equal(t, int64(-0x6A), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-12-17 11:01:15 +00:00
|
|
|
func TestINVERTWithConversion1(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.PUSHDATA2, 0, 0, opcode.INVERT)
|
|
|
|
vm := load(prog)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, int64(-1), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestINVERTWithConversion2(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.PUSH0, opcode.PUSH1, opcode.NUMEQUAL, opcode.INVERT)
|
|
|
|
vm := load(prog)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, int64(-1), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-09-06 06:12:19 +00:00
|
|
|
func TestCATBadNoArgs(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.CAT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCATBadOneArg(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.CAT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abc"))
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
2019-10-17 14:01:03 +00:00
|
|
|
func TestCATBadBigItem(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.CAT)
|
2019-10-17 14:01:03 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(make([]byte, MaxItemSize/2+1))
|
|
|
|
vm.estack.PushVal(make([]byte, MaxItemSize/2+1))
|
|
|
|
vm.Run()
|
|
|
|
assert.Equal(t, true, vm.HasFailed())
|
|
|
|
}
|
|
|
|
|
2019-09-06 06:12:19 +00:00
|
|
|
func TestCATGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.CAT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abc"))
|
|
|
|
vm.estack.PushVal([]byte("def"))
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, []byte("abcdef"), vm.estack.Peek(0).Bytes())
|
|
|
|
}
|
|
|
|
|
2019-09-10 14:28:53 +00:00
|
|
|
func TestCATInt0ByteArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.CAT)
|
2019-09-10 14:28:53 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
vm.estack.PushVal([]byte{})
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 14:28:53 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
2020-04-15 14:02:45 +00:00
|
|
|
assert.Equal(t, &ByteArrayItem{[]byte{}}, vm.estack.Pop().value)
|
2019-09-10 14:28:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCATByteArrayInt1(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.CAT)
|
2019-09-10 14:28:53 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte{})
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-10 14:28:53 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, &ByteArrayItem{[]byte{1}}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2019-09-06 06:12:19 +00:00
|
|
|
func TestSUBSTRBadNoArgs(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUBSTR)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSUBSTRBadOneArg(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUBSTR)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSUBSTRBadTwoArgs(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUBSTR)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSUBSTRGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUBSTR)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, []byte("bc"), vm.estack.Peek(0).Bytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSUBSTRBadOffset(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUBSTR)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
2019-09-18 11:19:58 +00:00
|
|
|
vm.estack.PushVal(7)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm.estack.PushVal(1)
|
2019-11-06 09:15:55 +00:00
|
|
|
|
2020-04-15 13:16:49 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
2019-09-18 11:19:58 +00:00
|
|
|
func TestSUBSTRBigLen(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUBSTR)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(6)
|
2020-04-15 13:16:49 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 09:00:11 +00:00
|
|
|
func TestSUBSTRBad387(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUBSTR)
|
2019-09-11 09:00:11 +00:00
|
|
|
vm := load(prog)
|
|
|
|
b := make([]byte, 6, 20)
|
|
|
|
copy(b, "abcdef")
|
|
|
|
vm.estack.PushVal(b)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(6)
|
2020-04-15 13:16:49 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 09:00:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSUBSTRBadNegativeOffset(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUBSTR)
|
2019-09-11 09:00:11 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
|
|
|
vm.estack.PushVal(-1)
|
|
|
|
vm.estack.PushVal(3)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 09:00:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSUBSTRBadNegativeLen(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.SUBSTR)
|
2019-09-11 09:00:11 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
|
|
|
vm.estack.PushVal(3)
|
|
|
|
vm.estack.PushVal(-1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 09:00:11 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 06:12:19 +00:00
|
|
|
func TestLEFTBadNoArgs(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.LEFT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestLEFTBadNoString(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.LEFT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 09:03:43 +00:00
|
|
|
func TestLEFTBadNegativeLen(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.LEFT)
|
2019-09-11 09:03:43 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
|
|
|
vm.estack.PushVal(-1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 09:03:43 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 06:12:19 +00:00
|
|
|
func TestLEFTGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.LEFT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, []byte("ab"), vm.estack.Peek(0).Bytes())
|
|
|
|
}
|
|
|
|
|
2019-09-09 14:05:40 +00:00
|
|
|
func TestLEFTGoodLen(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.LEFT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
|
|
|
vm.estack.PushVal(8)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-09 14:05:40 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, []byte("abcdef"), vm.estack.Peek(0).Bytes())
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestRIGHTBadNoArgs(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.RIGHT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestRIGHTBadNoString(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.RIGHT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 09:03:43 +00:00
|
|
|
func TestRIGHTBadNegativeLen(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.RIGHT)
|
2019-09-11 09:03:43 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
|
|
|
vm.estack.PushVal(-1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-11 09:03:43 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 06:12:19 +00:00
|
|
|
func TestRIGHTGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.RIGHT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
|
|
|
vm.estack.PushVal(2)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, []byte("ef"), vm.estack.Peek(0).Bytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRIGHTBadLen(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.RIGHT)
|
2019-09-06 06:12:19 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal([]byte("abcdef"))
|
|
|
|
vm.estack.PushVal(8)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 06:12:19 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 07:33:43 +00:00
|
|
|
func TestPACKBadLen(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PACK)
|
2019-09-06 07:33:43 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 07:33:43 +00:00
|
|
|
}
|
|
|
|
|
2019-10-17 08:07:44 +00:00
|
|
|
func TestPACKBigLen(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PACK)
|
2019-10-17 08:07:44 +00:00
|
|
|
vm := load(prog)
|
|
|
|
for i := 0; i <= MaxArraySize; i++ {
|
|
|
|
vm.estack.PushVal(0)
|
|
|
|
}
|
|
|
|
vm.estack.PushVal(MaxArraySize + 1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-10-17 08:07:44 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 07:33:43 +00:00
|
|
|
func TestPACKGoodZeroLen(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PACK)
|
2019-09-06 07:33:43 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(0)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 07:33:43 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, []StackItem{}, vm.estack.Peek(0).Array())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPACKGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.PACK)
|
2019-09-06 07:33:43 +00:00
|
|
|
elements := []int{55, 34, 42}
|
|
|
|
vm := load(prog)
|
|
|
|
// canary
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
for i := len(elements) - 1; i >= 0; i-- {
|
|
|
|
vm.estack.PushVal(elements[i])
|
|
|
|
}
|
|
|
|
vm.estack.PushVal(len(elements))
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 07:33:43 +00:00
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
a := vm.estack.Peek(0).Array()
|
|
|
|
assert.Equal(t, len(elements), len(a))
|
|
|
|
for i := 0; i < len(elements); i++ {
|
|
|
|
e := a[i].Value().(*big.Int)
|
|
|
|
assert.Equal(t, int64(elements[i]), e.Int64())
|
|
|
|
}
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Peek(1).BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
2019-09-06 08:32:20 +00:00
|
|
|
func TestUNPACKBadNotArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.UNPACK)
|
2019-09-06 08:32:20 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 08:32:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestUNPACKGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.UNPACK)
|
2019-09-06 08:32:20 +00:00
|
|
|
elements := []int{55, 34, 42}
|
|
|
|
vm := load(prog)
|
|
|
|
// canary
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(elements)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 08:32:20 +00:00
|
|
|
assert.Equal(t, 5, vm.estack.Len())
|
|
|
|
assert.Equal(t, int64(len(elements)), vm.estack.Peek(0).BigInt().Int64())
|
|
|
|
for k, v := range elements {
|
2019-09-09 08:23:27 +00:00
|
|
|
assert.Equal(t, int64(v), vm.estack.Peek(k+1).BigInt().Int64())
|
2019-09-06 08:32:20 +00:00
|
|
|
}
|
2019-09-09 08:23:27 +00:00
|
|
|
assert.Equal(t, int64(1), vm.estack.Peek(len(elements)+1).BigInt().Int64())
|
2019-09-06 08:32:20 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 09:24:08 +00:00
|
|
|
func TestREVERSEITEMSBadNotArray(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.REVERSEITEMS)
|
2019-09-06 08:32:20 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 08:32:20 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 09:24:08 +00:00
|
|
|
func testREVERSEITEMSIssue437(t *testing.T, i1, i2 opcode.Opcode, reversed bool) {
|
2019-10-18 10:01:51 +00:00
|
|
|
prog := makeProgram(
|
2019-12-03 14:05:06 +00:00
|
|
|
opcode.PUSH0, i1,
|
|
|
|
opcode.DUP, opcode.PUSH1, opcode.APPEND,
|
|
|
|
opcode.DUP, opcode.PUSH2, opcode.APPEND,
|
2020-04-24 09:24:08 +00:00
|
|
|
opcode.DUP, i2, opcode.REVERSEITEMS)
|
2019-10-18 10:01:51 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.Run()
|
|
|
|
|
|
|
|
arr := make([]StackItem, 2)
|
|
|
|
if reversed {
|
|
|
|
arr[0] = makeStackItem(2)
|
|
|
|
arr[1] = makeStackItem(1)
|
|
|
|
} else {
|
|
|
|
arr[0] = makeStackItem(1)
|
|
|
|
arr[1] = makeStackItem(2)
|
|
|
|
}
|
|
|
|
assert.Equal(t, false, vm.HasFailed())
|
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
2019-12-03 14:05:06 +00:00
|
|
|
if i1 == opcode.NEWARRAY {
|
2019-10-18 10:01:51 +00:00
|
|
|
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
|
|
|
|
} else {
|
|
|
|
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-24 09:24:08 +00:00
|
|
|
func TestREVERSEITEMSIssue437(t *testing.T) {
|
|
|
|
t.Run("Array+Array", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWARRAY, opcode.NEWARRAY, true) })
|
|
|
|
t.Run("Struct+Struct", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWSTRUCT, opcode.NEWSTRUCT, true) })
|
|
|
|
t.Run("Array+Struct", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWARRAY, opcode.NEWSTRUCT, false) })
|
|
|
|
t.Run("Struct+Array", func(t *testing.T) { testREVERSEITEMSIssue437(t, opcode.NEWSTRUCT, opcode.NEWARRAY, false) })
|
2019-10-18 10:01:51 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 09:24:08 +00:00
|
|
|
func TestREVERSEITEMSGoodOneElem(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.DUP, opcode.REVERSEITEMS)
|
2019-09-06 08:32:20 +00:00
|
|
|
elements := []int{22}
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(elements)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 08:32:20 +00:00
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
a := vm.estack.Peek(0).Array()
|
|
|
|
assert.Equal(t, len(elements), len(a))
|
|
|
|
e := a[0].Value().(*big.Int)
|
|
|
|
assert.Equal(t, int64(elements[0]), e.Int64())
|
|
|
|
}
|
|
|
|
|
2020-04-24 09:24:08 +00:00
|
|
|
func TestREVERSEITEMSGoodStruct(t *testing.T) {
|
2019-09-12 13:54:22 +00:00
|
|
|
eodd := []int{22, 34, 42, 55, 81}
|
|
|
|
even := []int{22, 34, 42, 55, 81, 99}
|
|
|
|
eall := [][]int{eodd, even}
|
|
|
|
|
|
|
|
for _, elements := range eall {
|
2020-04-24 09:24:08 +00:00
|
|
|
prog := makeProgram(opcode.DUP, opcode.REVERSEITEMS)
|
2019-09-12 13:54:22 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
|
|
|
|
arr := make([]StackItem, len(elements))
|
|
|
|
for i := range elements {
|
|
|
|
arr[i] = makeStackItem(elements[i])
|
|
|
|
}
|
|
|
|
vm.estack.Push(&Element{value: &StructItem{arr}})
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-12 13:54:22 +00:00
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
a := vm.estack.Peek(0).Array()
|
|
|
|
assert.Equal(t, len(elements), len(a))
|
|
|
|
for k, v := range elements {
|
|
|
|
e := a[len(a)-1-k].Value().(*big.Int)
|
|
|
|
assert.Equal(t, int64(v), e.Int64())
|
|
|
|
}
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Peek(1).BigInt().Int64())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-24 09:24:08 +00:00
|
|
|
func TestREVERSEITEMSGood(t *testing.T) {
|
2019-09-06 08:32:20 +00:00
|
|
|
eodd := []int{22, 34, 42, 55, 81}
|
|
|
|
even := []int{22, 34, 42, 55, 81, 99}
|
|
|
|
eall := [][]int{eodd, even}
|
|
|
|
|
|
|
|
for _, elements := range eall {
|
2020-04-24 09:24:08 +00:00
|
|
|
prog := makeProgram(opcode.DUP, opcode.REVERSEITEMS)
|
2019-09-06 08:32:20 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(elements)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 08:32:20 +00:00
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
a := vm.estack.Peek(0).Array()
|
|
|
|
assert.Equal(t, len(elements), len(a))
|
|
|
|
for k, v := range elements {
|
2019-09-09 08:23:27 +00:00
|
|
|
e := a[len(a)-1-k].Value().(*big.Int)
|
2019-09-06 08:32:20 +00:00
|
|
|
assert.Equal(t, int64(v), e.Int64())
|
|
|
|
}
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Peek(1).BigInt().Int64())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestREMOVEBadNoArgs(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.REMOVE)
|
2019-09-06 08:32:20 +00:00
|
|
|
vm := load(prog)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 08:32:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestREMOVEBadOneArg(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.REMOVE)
|
2019-09-06 08:32:20 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 08:32:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestREMOVEBadNotArray(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.REMOVE)
|
2019-09-06 08:32:20 +00:00
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(1)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 08:32:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestREMOVEBadIndex(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.REMOVE)
|
2019-09-06 08:32:20 +00:00
|
|
|
elements := []int{22, 34, 42, 55, 81}
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(elements)
|
|
|
|
vm.estack.PushVal(10)
|
2019-10-22 10:44:14 +00:00
|
|
|
checkVMFailed(t, vm)
|
2019-09-06 08:32:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestREMOVEGood(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.DUP, opcode.PUSH2, opcode.REMOVE)
|
2019-09-06 08:32:20 +00:00
|
|
|
elements := []int{22, 34, 42, 55, 81}
|
|
|
|
reselements := []int{22, 34, 55, 81}
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(elements)
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-06 08:32:20 +00:00
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
2019-09-12 08:32:09 +00:00
|
|
|
assert.Equal(t, makeStackItem(reselements), vm.estack.Pop().value)
|
|
|
|
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
2019-09-06 08:32:20 +00:00
|
|
|
}
|
|
|
|
|
2019-09-24 13:16:24 +00:00
|
|
|
func TestREMOVEMap(t *testing.T) {
|
2019-12-03 14:05:06 +00:00
|
|
|
prog := makeProgram(opcode.REMOVE, opcode.PUSH5, opcode.HASKEY)
|
2019-09-24 13:16:24 +00:00
|
|
|
vm := load(prog)
|
|
|
|
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(makeStackItem(5), makeStackItem(3))
|
|
|
|
m.Add(makeStackItem([]byte{0, 1}), makeStackItem([]byte{2, 3}))
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
vm.estack.Push(&Element{value: m})
|
|
|
|
vm.estack.PushVal(makeStackItem(5))
|
|
|
|
|
2019-10-22 10:44:14 +00:00
|
|
|
runVM(t, vm)
|
2019-09-24 13:16:24 +00:00
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, makeStackItem(false), vm.estack.Pop().value)
|
|
|
|
}
|
|
|
|
|
2020-04-24 10:02:38 +00:00
|
|
|
func testCLEARITEMS(t *testing.T, item StackItem) {
|
|
|
|
prog := makeProgram(opcode.DUP, opcode.DUP, opcode.CLEARITEMS, opcode.SIZE)
|
|
|
|
v := load(prog)
|
|
|
|
v.estack.PushVal(item)
|
|
|
|
runVM(t, v)
|
|
|
|
require.Equal(t, 2, v.estack.Len())
|
|
|
|
require.EqualValues(t, 2, v.size) // empty collection + it's size
|
|
|
|
require.EqualValues(t, 0, v.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCLEARITEMS(t *testing.T) {
|
|
|
|
arr := []StackItem{NewBigIntegerItem(big.NewInt(1)), NewByteArrayItem([]byte{1})}
|
|
|
|
m := NewMapItem()
|
|
|
|
m.Add(NewBigIntegerItem(big.NewInt(1)), NewByteArrayItem([]byte{}))
|
|
|
|
m.Add(NewByteArrayItem([]byte{42}), NewBigIntegerItem(big.NewInt(2)))
|
|
|
|
|
|
|
|
testCases := map[string]StackItem{
|
|
|
|
"empty Array": NewArrayItem([]StackItem{}),
|
|
|
|
"filled Array": NewArrayItem(arr),
|
|
|
|
"empty Struct": NewStructItem([]StackItem{}),
|
|
|
|
"filled Struct": NewStructItem(arr),
|
|
|
|
"empty Map": NewMapItem(),
|
|
|
|
"filled Map": m,
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, item := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) { testCLEARITEMS(t, item) })
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("Integer", func(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.CLEARITEMS)
|
|
|
|
v := load(prog)
|
|
|
|
v.estack.PushVal(1)
|
|
|
|
checkVMFailed(t, v)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-12-16 16:02:40 +00:00
|
|
|
func TestSWAPGood(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.SWAP)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
assert.Equal(t, int64(2), vm.estack.Pop().BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(4), vm.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSWAPBad1(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.SWAP)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSWAPBad2(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.SWAP)
|
|
|
|
vm := load(prog)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestXSWAPGood(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.XSWAP)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(3)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(5)
|
|
|
|
vm.estack.PushVal(3)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 5, vm.estack.Len())
|
|
|
|
assert.Equal(t, int64(2), vm.estack.Pop().BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(4), vm.estack.Pop().BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(3), vm.estack.Pop().BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(5), vm.estack.Pop().BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestXSWAPBad1(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.XSWAP)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(-1)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestXSWAPBad2(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.XSWAP)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(1)
|
|
|
|
vm.estack.PushVal(2)
|
|
|
|
vm.estack.PushVal(3)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
vm.estack.PushVal(4)
|
|
|
|
checkVMFailed(t, vm)
|
|
|
|
}
|
|
|
|
|
2019-12-17 13:38:42 +00:00
|
|
|
func TestDupInt(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.DUP, opcode.ABS)
|
|
|
|
vm := load(prog)
|
|
|
|
vm.estack.PushVal(-1)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
assert.Equal(t, int64(1), vm.estack.Pop().BigInt().Int64())
|
|
|
|
assert.Equal(t, int64(-1), vm.estack.Pop().BigInt().Int64())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDupByteArray(t *testing.T) {
|
2020-04-21 13:45:48 +00:00
|
|
|
prog := makeProgram(opcode.PUSHDATA1, 2, 1, 0,
|
2019-12-17 13:38:42 +00:00
|
|
|
opcode.DUP,
|
|
|
|
opcode.PUSH1,
|
|
|
|
opcode.LEFT,
|
2020-04-21 13:45:48 +00:00
|
|
|
opcode.PUSHDATA1, 1, 2,
|
2019-12-17 13:38:42 +00:00
|
|
|
opcode.CAT)
|
|
|
|
vm := load(prog)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
assert.Equal(t, []byte{0x01, 0x02}, vm.estack.Pop().Bytes())
|
|
|
|
assert.Equal(t, []byte{0x01, 0x00}, vm.estack.Pop().Bytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDupBool(t *testing.T) {
|
|
|
|
prog := makeProgram(opcode.PUSH0, opcode.NOT,
|
|
|
|
opcode.DUP,
|
|
|
|
opcode.PUSH1, opcode.NOT,
|
|
|
|
opcode.BOOLAND)
|
|
|
|
vm := load(prog)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 2, vm.estack.Len())
|
|
|
|
assert.Equal(t, false, vm.estack.Pop().Bool())
|
|
|
|
assert.Equal(t, true, vm.estack.Pop().Bool())
|
|
|
|
}
|
|
|
|
|
2019-12-17 17:31:16 +00:00
|
|
|
func TestSHA1(t *testing.T) {
|
|
|
|
// 0x0100 hashes to 0e356ba505631fbf715758bed27d503f8b260e3a
|
|
|
|
res := "0e356ba505631fbf715758bed27d503f8b260e3a"
|
2020-04-21 13:45:48 +00:00
|
|
|
prog := makeProgram(opcode.PUSHDATA1, 2, 1, 0,
|
2019-12-17 17:31:16 +00:00
|
|
|
opcode.SHA1)
|
|
|
|
vm := load(prog)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, res, hex.EncodeToString(vm.estack.Pop().Bytes()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSHA256(t *testing.T) {
|
|
|
|
// 0x0100 hashes to 47dc540c94ceb704a23875c11273e16bb0b8a87aed84de911f2133568115f254
|
|
|
|
res := "47dc540c94ceb704a23875c11273e16bb0b8a87aed84de911f2133568115f254"
|
2020-04-21 13:45:48 +00:00
|
|
|
prog := makeProgram(opcode.PUSHDATA1, 2, 1, 0,
|
2019-12-17 17:31:16 +00:00
|
|
|
opcode.SHA256)
|
|
|
|
vm := load(prog)
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, 1, vm.estack.Len())
|
|
|
|
assert.Equal(t, res, hex.EncodeToString(vm.estack.Pop().Bytes()))
|
|
|
|
}
|
|
|
|
|
2020-04-07 08:20:48 +00:00
|
|
|
var opcodesTestCases = map[opcode.Opcode][]struct {
|
|
|
|
name string
|
|
|
|
args []interface{}
|
|
|
|
expected interface{}
|
|
|
|
actual func(vm *VM) interface{}
|
|
|
|
}{
|
|
|
|
opcode.AND: {
|
|
|
|
{
|
|
|
|
name: "1_1",
|
|
|
|
args: []interface{}{1, 1},
|
|
|
|
expected: int64(1),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "1_0",
|
|
|
|
args: []interface{}{1, 0},
|
|
|
|
expected: int64(0),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "0_1",
|
|
|
|
args: []interface{}{0, 1},
|
|
|
|
expected: int64(0),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "0_0",
|
|
|
|
args: []interface{}{0, 0},
|
|
|
|
expected: int64(0),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "random_values",
|
|
|
|
args: []interface{}{
|
|
|
|
[]byte{1, 0, 1, 0, 1, 0, 1, 1},
|
|
|
|
[]byte{1, 1, 0, 0, 0, 0, 0, 1},
|
|
|
|
},
|
|
|
|
expected: []byte{1, 0, 0, 0, 0, 0, 0, 1},
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().Bytes()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
opcode.OR: {
|
|
|
|
{
|
|
|
|
name: "1_1",
|
|
|
|
args: []interface{}{1, 1},
|
|
|
|
expected: int64(1),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "0_0",
|
|
|
|
args: []interface{}{0, 0},
|
|
|
|
expected: int64(0),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "0_1",
|
|
|
|
args: []interface{}{0, 1},
|
|
|
|
expected: int64(1),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "1_0",
|
|
|
|
args: []interface{}{1, 0},
|
|
|
|
expected: int64(1),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "random_values",
|
|
|
|
args: []interface{}{
|
|
|
|
[]byte{1, 0, 1, 0, 1, 0, 1, 1},
|
|
|
|
[]byte{1, 1, 0, 0, 0, 0, 0, 1},
|
|
|
|
},
|
|
|
|
expected: []byte{1, 1, 1, 0, 1, 0, 1, 1},
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().Bytes()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
opcode.XOR: {
|
|
|
|
{
|
|
|
|
name: "1_1",
|
|
|
|
args: []interface{}{1, 1},
|
|
|
|
expected: int64(0),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "0_0",
|
|
|
|
args: []interface{}{0, 0},
|
|
|
|
expected: int64(0),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "0_1",
|
|
|
|
args: []interface{}{0, 1},
|
|
|
|
expected: int64(1),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "1_0",
|
|
|
|
args: []interface{}{1, 0},
|
|
|
|
expected: int64(1),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "random_values",
|
|
|
|
args: []interface{}{
|
|
|
|
[]byte{1, 0, 1, 0, 1, 0, 1, 1},
|
|
|
|
[]byte{1, 1, 0, 0, 0, 0, 0, 1},
|
|
|
|
},
|
|
|
|
expected: []byte{0, 1, 1, 0, 1, 0, 1},
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().Bytes()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
opcode.BOOLOR: {
|
|
|
|
{
|
|
|
|
name: "1_1",
|
|
|
|
args: []interface{}{true, true},
|
|
|
|
expected: true,
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().Bool()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "0_0",
|
|
|
|
args: []interface{}{false, false},
|
|
|
|
expected: false,
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().Bool()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "0_1",
|
|
|
|
args: []interface{}{false, true},
|
|
|
|
expected: true,
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().Bool()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "1_0",
|
|
|
|
args: []interface{}{true, false},
|
|
|
|
expected: true,
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().Bool()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
opcode.MIN: {
|
|
|
|
{
|
|
|
|
name: "3_5",
|
|
|
|
args: []interface{}{3, 5},
|
|
|
|
expected: int64(3),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "5_3",
|
|
|
|
args: []interface{}{5, 3},
|
|
|
|
expected: int64(3),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "3_3",
|
|
|
|
args: []interface{}{3, 3},
|
|
|
|
expected: int64(3),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
opcode.MAX: {
|
|
|
|
{
|
|
|
|
name: "3_5",
|
|
|
|
args: []interface{}{3, 5},
|
|
|
|
expected: int64(5),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "5_3",
|
|
|
|
args: []interface{}{5, 3},
|
|
|
|
expected: int64(5),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "3_3",
|
|
|
|
args: []interface{}{3, 3},
|
|
|
|
expected: int64(3),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
opcode.WITHIN: {
|
|
|
|
{
|
|
|
|
name: "within",
|
|
|
|
args: []interface{}{4, 3, 5},
|
|
|
|
expected: true,
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().Bool()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "less",
|
|
|
|
args: []interface{}{2, 3, 5},
|
|
|
|
expected: false,
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().Bool()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "more",
|
|
|
|
args: []interface{}{6, 3, 5},
|
|
|
|
expected: false,
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().Bool()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
opcode.NEGATE: {
|
|
|
|
{
|
|
|
|
name: "3",
|
|
|
|
args: []interface{}{3},
|
|
|
|
expected: int64(-3),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "-3",
|
|
|
|
args: []interface{}{-3},
|
|
|
|
expected: int64(3),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "0",
|
|
|
|
args: []interface{}{0},
|
|
|
|
expected: int64(0),
|
|
|
|
actual: func(vm *VM) interface{} {
|
|
|
|
return vm.estack.Pop().BigInt().Int64()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBitAndNumericOpcodes(t *testing.T) {
|
|
|
|
for code, opcodeTestCases := range opcodesTestCases {
|
|
|
|
t.Run(code.String(), func(t *testing.T) {
|
|
|
|
for _, testCase := range opcodeTestCases {
|
|
|
|
prog := makeProgram(code)
|
|
|
|
vm := load(prog)
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
|
|
for _, arg := range testCase.args {
|
|
|
|
vm.estack.PushVal(arg)
|
|
|
|
}
|
|
|
|
runVM(t, vm)
|
|
|
|
assert.Equal(t, testCase.expected, testCase.actual(vm))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-03 14:05:06 +00:00
|
|
|
func makeProgram(opcodes ...opcode.Opcode) []byte {
|
2019-08-14 12:40:31 +00:00
|
|
|
prog := make([]byte, len(opcodes)+1) // RET
|
2018-03-30 16:15:06 +00:00
|
|
|
for i := 0; i < len(opcodes); i++ {
|
|
|
|
prog[i] = byte(opcodes[i])
|
|
|
|
}
|
2019-12-03 14:05:06 +00:00
|
|
|
prog[len(prog)-1] = byte(opcode.RET)
|
2018-03-30 16:15:06 +00:00
|
|
|
return prog
|
|
|
|
}
|
|
|
|
|
|
|
|
func load(prog []byte) *VM {
|
2019-10-22 10:44:14 +00:00
|
|
|
vm := New()
|
2019-10-25 14:25:46 +00:00
|
|
|
vm.LoadScript(prog)
|
2018-03-30 16:15:06 +00:00
|
|
|
return vm
|
|
|
|
}
|
|
|
|
|
|
|
|
func randomBytes(n int) []byte {
|
|
|
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
|
|
b := make([]byte, n)
|
|
|
|
for i := range b {
|
|
|
|
b[i] = charset[rand.Intn(len(charset))]
|
|
|
|
}
|
|
|
|
return b
|
|
|
|
}
|