Merge pull request #394 from nspcc-dev/fix/json-tests-bugs
VM: fix some bugs from neo-vm JSON tests
This commit is contained in:
commit
0838948540
9 changed files with 323 additions and 64 deletions
|
@ -121,6 +121,8 @@ func (e *Element) Array() []StackItem {
|
|||
switch t := e.value.(type) {
|
||||
case *ArrayItem:
|
||||
return t.value
|
||||
case *StructItem:
|
||||
return t.value
|
||||
default:
|
||||
panic("element is not an array")
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ var binaryExprTestCases = []testCase{
|
|||
return x
|
||||
}
|
||||
`,
|
||||
big.NewInt(0),
|
||||
[]byte{},
|
||||
},
|
||||
{
|
||||
"simple div",
|
||||
|
@ -86,7 +86,7 @@ var binaryExprTestCases = []testCase{
|
|||
return 0
|
||||
}
|
||||
`,
|
||||
big.NewInt(0),
|
||||
[]byte{},
|
||||
},
|
||||
{
|
||||
"compare equal strings with eql",
|
||||
|
@ -128,7 +128,7 @@ var binaryExprTestCases = []testCase{
|
|||
return 0
|
||||
}
|
||||
`,
|
||||
big.NewInt(0),
|
||||
[]byte{},
|
||||
},
|
||||
{
|
||||
"compare equal ints with eql",
|
||||
|
@ -156,7 +156,7 @@ var binaryExprTestCases = []testCase{
|
|||
return 0
|
||||
}
|
||||
`,
|
||||
big.NewInt(0),
|
||||
[]byte{},
|
||||
},
|
||||
{
|
||||
"compare not equal ints with eql",
|
||||
|
@ -170,7 +170,7 @@ var binaryExprTestCases = []testCase{
|
|||
return 0
|
||||
}
|
||||
`,
|
||||
big.NewInt(0),
|
||||
[]byte{},
|
||||
},
|
||||
{
|
||||
"compare not equal ints with neq",
|
||||
|
|
|
@ -275,7 +275,7 @@ func TestIfUnaryInvert(t *testing.T) {
|
|||
return 0
|
||||
}
|
||||
`
|
||||
eval(t, src, big.NewInt(0))
|
||||
eval(t, src, []byte{})
|
||||
}
|
||||
|
||||
func TestAppendByte(t *testing.T) {
|
||||
|
|
|
@ -35,7 +35,7 @@ func TestNotAssignedFunctionCall(t *testing.T) {
|
|||
return 0
|
||||
}
|
||||
`
|
||||
eval(t, src, big.NewInt(0))
|
||||
eval(t, src, []byte{})
|
||||
}
|
||||
|
||||
func TestMultipleFunctionCalls(t *testing.T) {
|
||||
|
|
|
@ -30,7 +30,7 @@ func TestGT(t *testing.T) {
|
|||
return 0
|
||||
}
|
||||
`
|
||||
eval(t, src, big.NewInt(0))
|
||||
eval(t, src, []byte{})
|
||||
}
|
||||
|
||||
func TestGTE(t *testing.T) {
|
||||
|
@ -44,7 +44,7 @@ func TestGTE(t *testing.T) {
|
|||
return 0
|
||||
}
|
||||
`
|
||||
eval(t, src, big.NewInt(0))
|
||||
eval(t, src, []byte{})
|
||||
}
|
||||
|
||||
func TestLAND(t *testing.T) {
|
||||
|
@ -89,5 +89,5 @@ func TestNestedIF(t *testing.T) {
|
|||
return 0
|
||||
}
|
||||
`
|
||||
eval(t, src, big.NewInt(0))
|
||||
eval(t, src, []byte{})
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ func TestImportStruct(t *testing.T) {
|
|||
return b.Y
|
||||
}
|
||||
`
|
||||
eval(t, src, big.NewInt(0))
|
||||
eval(t, src, []byte{})
|
||||
}
|
||||
|
||||
func TestMultipleDirFileImport(t *testing.T) {
|
||||
|
|
|
@ -179,7 +179,7 @@ var structTestCases = []testCase{
|
|||
return t.y
|
||||
}
|
||||
`,
|
||||
big.NewInt(0),
|
||||
[]byte{},
|
||||
},
|
||||
{
|
||||
"test return struct from func",
|
||||
|
@ -209,7 +209,7 @@ var structTestCases = []testCase{
|
|||
vm.NewBigIntegerItem(1),
|
||||
vm.NewBigIntegerItem(2),
|
||||
vm.NewByteArrayItem([]byte("hello")),
|
||||
vm.NewBigIntegerItem(0),
|
||||
vm.NewByteArrayItem([]byte{}),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
97
pkg/vm/vm.go
97
pkg/vm/vm.go
|
@ -257,7 +257,7 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
v.estack.PushVal(val)
|
||||
|
||||
case PUSH0:
|
||||
v.estack.PushVal(0)
|
||||
v.estack.PushVal([]byte{})
|
||||
|
||||
case PUSHDATA1:
|
||||
n := ctx.readByte()
|
||||
|
@ -375,7 +375,7 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
|
||||
case XTUCK:
|
||||
n := int(v.estack.Pop().BigInt().Int64())
|
||||
if n < 0 {
|
||||
if n <= 0 {
|
||||
panic("XTUCK: invalid length")
|
||||
}
|
||||
a := v.estack.Dup(0)
|
||||
|
@ -388,21 +388,20 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
v.estack.InsertAt(a, n)
|
||||
|
||||
case ROT:
|
||||
c := v.estack.Pop()
|
||||
b := v.estack.Pop()
|
||||
a := v.estack.Pop()
|
||||
|
||||
v.estack.Push(b)
|
||||
v.estack.Push(c)
|
||||
v.estack.Push(a)
|
||||
e := v.estack.RemoveAt(2)
|
||||
if e == nil {
|
||||
panic("no top-level element found")
|
||||
}
|
||||
v.estack.Push(e)
|
||||
|
||||
case DEPTH:
|
||||
v.estack.PushVal(v.estack.Len())
|
||||
|
||||
case NIP:
|
||||
elem := v.estack.Pop()
|
||||
_ = v.estack.Pop()
|
||||
v.estack.Push(elem)
|
||||
elem := v.estack.RemoveAt(1)
|
||||
if elem == nil {
|
||||
panic("no second element found")
|
||||
}
|
||||
|
||||
case OVER:
|
||||
b := v.estack.Pop()
|
||||
|
@ -441,11 +440,20 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
}
|
||||
|
||||
case DROP:
|
||||
if v.estack.Len() < 1 {
|
||||
panic("stack is too small")
|
||||
}
|
||||
v.estack.Pop()
|
||||
|
||||
case EQUAL:
|
||||
b := v.estack.Pop()
|
||||
if b == nil {
|
||||
panic("no top-level element found")
|
||||
}
|
||||
a := v.estack.Pop()
|
||||
if a == nil {
|
||||
panic("no second-to-the-top element found")
|
||||
}
|
||||
v.estack.PushVal(reflect.DeepEqual(a, b))
|
||||
|
||||
// Bit operations.
|
||||
|
@ -497,11 +505,17 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
|
||||
case SHL:
|
||||
b := v.estack.Pop().BigInt()
|
||||
if b.Int64() == 0 {
|
||||
return
|
||||
}
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(new(big.Int).Lsh(a, uint(b.Int64())))
|
||||
|
||||
case SHR:
|
||||
b := v.estack.Pop().BigInt()
|
||||
if b.Int64() == 0 {
|
||||
return
|
||||
}
|
||||
a := v.estack.Pop().BigInt()
|
||||
v.estack.PushVal(new(big.Int).Rsh(a, uint(b.Int64())))
|
||||
|
||||
|
@ -601,31 +615,27 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
case NEWARRAY:
|
||||
item := v.estack.Pop()
|
||||
switch t := item.value.(type) {
|
||||
case *BigIntegerItem:
|
||||
n := t.value.Int64()
|
||||
items := make([]StackItem, n)
|
||||
v.estack.PushVal(&ArrayItem{items})
|
||||
case *StructItem:
|
||||
v.estack.PushVal(&ArrayItem{t.value})
|
||||
case *ArrayItem:
|
||||
v.estack.PushVal(t)
|
||||
default:
|
||||
panic("NEWARRAY: invalid operand")
|
||||
n := item.BigInt()
|
||||
items := makeArrayOfFalses(int(n.Int64()))
|
||||
v.estack.PushVal(&ArrayItem{items})
|
||||
}
|
||||
|
||||
case NEWSTRUCT:
|
||||
item := v.estack.Pop()
|
||||
switch t := item.value.(type) {
|
||||
case *BigIntegerItem:
|
||||
n := t.value.Int64()
|
||||
items := make([]StackItem, n)
|
||||
v.estack.PushVal(&StructItem{items})
|
||||
case *ArrayItem:
|
||||
v.estack.PushVal(&StructItem{t.value})
|
||||
case *StructItem:
|
||||
v.estack.PushVal(t)
|
||||
default:
|
||||
panic("NEWSTRUCT: invalid operand")
|
||||
n := item.BigInt()
|
||||
items := makeArrayOfFalses(int(n.Int64()))
|
||||
v.estack.PushVal(&StructItem{items})
|
||||
}
|
||||
|
||||
case APPEND:
|
||||
|
@ -683,7 +693,12 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
item := arr[index]
|
||||
v.estack.PushVal(item)
|
||||
default:
|
||||
panic("PICKITEM: unknown type")
|
||||
arr := obj.Bytes()
|
||||
if index < 0 || index >= len(arr) {
|
||||
panic("PICKITEM: invalid index")
|
||||
}
|
||||
item := arr[index]
|
||||
v.estack.PushVal(int(item))
|
||||
}
|
||||
|
||||
case SETITEM:
|
||||
|
@ -707,7 +722,7 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
}
|
||||
|
||||
case REVERSE:
|
||||
a := v.estack.Peek(0).Array()
|
||||
a := v.estack.Pop().Array()
|
||||
if len(a) > 1 {
|
||||
for i, j := 0, len(a)-1; i <= j; i, j = i+1, j-1 {
|
||||
a[i], a[j] = a[j], a[i]
|
||||
|
@ -715,10 +730,25 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
}
|
||||
case REMOVE:
|
||||
key := int(v.estack.Pop().BigInt().Int64())
|
||||
elem := v.estack.Peek(0)
|
||||
a := elem.Array()
|
||||
elem := v.estack.Pop()
|
||||
switch t := elem.value.(type) {
|
||||
case *ArrayItem:
|
||||
a := t.value
|
||||
if key < 0 || key >= len(a) {
|
||||
panic("REMOVE: invalid index")
|
||||
}
|
||||
a = append(a[:key], a[key+1:]...)
|
||||
elem.value = makeStackItem(a)
|
||||
t.value = a
|
||||
case *StructItem:
|
||||
a := t.value
|
||||
if key < 0 || key >= len(a) {
|
||||
panic("REMOVE: invalid index")
|
||||
}
|
||||
a = append(a[:key], a[key+1:]...)
|
||||
t.value = a
|
||||
default:
|
||||
panic("REMOVE: invalid type")
|
||||
}
|
||||
|
||||
case ARRAYSIZE:
|
||||
elem := v.estack.Pop()
|
||||
|
@ -735,10 +765,7 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
|
||||
case SIZE:
|
||||
elem := v.estack.Pop()
|
||||
arr, ok := elem.value.Value().([]uint8)
|
||||
if !ok {
|
||||
panic("SIZE: item not of type []uint8")
|
||||
}
|
||||
arr := elem.Bytes()
|
||||
v.estack.PushVal(len(arr))
|
||||
|
||||
case JMP, JMPIF, JMPIFNOT:
|
||||
|
@ -840,6 +867,14 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
|||
}
|
||||
}
|
||||
|
||||
func makeArrayOfFalses(n int) []StackItem {
|
||||
items := make([]StackItem, n)
|
||||
for i := range items {
|
||||
items[i] = &BoolItem{false}
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func init() {
|
||||
log.SetPrefix("NEO-GO-VM > ")
|
||||
log.SetFlags(0)
|
||||
|
|
|
@ -283,6 +283,50 @@ func TestSub(t *testing.T) {
|
|||
assert.Equal(t, int64(2), vm.estack.Pop().BigInt().Int64())
|
||||
}
|
||||
|
||||
func TestSHRGood(t *testing.T) {
|
||||
prog := makeProgram(SHR)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(4)
|
||||
vm.estack.PushVal(2)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestSHRZero(t *testing.T) {
|
||||
prog := makeProgram(SHR)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal([]byte{0, 1})
|
||||
vm.estack.PushVal(0)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, makeStackItem([]byte{0, 1}), vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestSHLGood(t *testing.T) {
|
||||
prog := makeProgram(SHL)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(4)
|
||||
vm.estack.PushVal(2)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, makeStackItem(16), vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestSHLZero(t *testing.T) {
|
||||
prog := makeProgram(SHL)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal([]byte{0, 1})
|
||||
vm.estack.PushVal(0)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, makeStackItem([]byte{0, 1}), vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestLT(t *testing.T) {
|
||||
prog := makeProgram(LT)
|
||||
vm := load(prog)
|
||||
|
@ -335,6 +379,32 @@ func TestDepth(t *testing.T) {
|
|||
assert.Equal(t, int64(3), vm.estack.Pop().BigInt().Int64())
|
||||
}
|
||||
|
||||
func TestEQUALNoArguments(t *testing.T) {
|
||||
prog := makeProgram(EQUAL)
|
||||
vm := load(prog)
|
||||
vm.Run()
|
||||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
}
|
||||
|
||||
func TestEQUALBad1Argument(t *testing.T) {
|
||||
prog := makeProgram(EQUAL)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(1)
|
||||
vm.Run()
|
||||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
}
|
||||
|
||||
func TestEQUALGoodInteger(t *testing.T) {
|
||||
prog := makeProgram(EQUAL)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(5)
|
||||
vm.estack.PushVal(5)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, &BoolItem{true}, vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestNumEqual(t *testing.T) {
|
||||
prog := makeProgram(NUMEQUAL)
|
||||
vm := load(prog)
|
||||
|
@ -371,7 +441,7 @@ func TestNEWARRAYInteger(t *testing.T) {
|
|||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, &ArrayItem{make([]StackItem, 1)}, vm.estack.Pop().value)
|
||||
assert.Equal(t, &ArrayItem{[]StackItem{makeStackItem(false)}}, vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestNEWARRAYStruct(t *testing.T) {
|
||||
|
@ -396,12 +466,14 @@ func TestNEWARRAYArray(t *testing.T) {
|
|||
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestNEWARRAYWrongType(t *testing.T) {
|
||||
func TestNEWARRAYByteArray(t *testing.T) {
|
||||
prog := makeProgram(NEWARRAY)
|
||||
vm := load(prog)
|
||||
vm.estack.Push(NewElement([]byte{}))
|
||||
vm.estack.PushVal([]byte{})
|
||||
vm.Run()
|
||||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, &ArrayItem{[]StackItem{}}, vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestNEWSTRUCTInteger(t *testing.T) {
|
||||
|
@ -411,7 +483,7 @@ func TestNEWSTRUCTInteger(t *testing.T) {
|
|||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, &StructItem{make([]StackItem, 1)}, vm.estack.Pop().value)
|
||||
assert.Equal(t, &StructItem{[]StackItem{makeStackItem(false)}}, vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestNEWSTRUCTArray(t *testing.T) {
|
||||
|
@ -436,12 +508,14 @@ func TestNEWSTRUCTStruct(t *testing.T) {
|
|||
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestNEWSTRUCTWrongType(t *testing.T) {
|
||||
func TestNEWSTRUCTByteArray(t *testing.T) {
|
||||
prog := makeProgram(NEWSTRUCT)
|
||||
vm := load(prog)
|
||||
vm.estack.Push(NewElement([]byte{}))
|
||||
vm.estack.PushVal([]byte{})
|
||||
vm.Run()
|
||||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, &StructItem{[]StackItem{}}, vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestAPPENDArray(t *testing.T) {
|
||||
|
@ -488,6 +562,64 @@ func TestAPPENDWrongType(t *testing.T) {
|
|||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
}
|
||||
|
||||
func TestPICKITEMBadIndex(t *testing.T) {
|
||||
prog := makeProgram(PICKITEM)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal([]StackItem{})
|
||||
vm.estack.PushVal(0)
|
||||
vm.Run()
|
||||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
}
|
||||
|
||||
func TestPICKITEMArray(t *testing.T) {
|
||||
prog := makeProgram(PICKITEM)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal([]StackItem{makeStackItem(1), makeStackItem(2)})
|
||||
vm.estack.PushVal(1)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestPICKITEMByteArray(t *testing.T) {
|
||||
prog := makeProgram(PICKITEM)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal([]byte{1, 2})
|
||||
vm.estack.PushVal(1)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestSIZENoArgument(t *testing.T) {
|
||||
prog := makeProgram(SIZE)
|
||||
vm := load(prog)
|
||||
vm.Run()
|
||||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
}
|
||||
|
||||
func TestSIZEByteArray(t *testing.T) {
|
||||
prog := makeProgram(SIZE)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal([]byte{0, 1})
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestSIZEBool(t *testing.T) {
|
||||
prog := makeProgram(SIZE)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(false)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestSIGNNoArgument(t *testing.T) {
|
||||
prog := makeProgram(SIGN)
|
||||
vm := load(prog)
|
||||
|
@ -633,6 +765,29 @@ func TestPICKgood(t *testing.T) {
|
|||
assert.Equal(t, int64(result), vm.estack.Pop().BigInt().Int64())
|
||||
}
|
||||
|
||||
func TestROTBad(t *testing.T) {
|
||||
prog := makeProgram(ROT)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(1)
|
||||
vm.estack.PushVal(2)
|
||||
vm.Run()
|
||||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
}
|
||||
|
||||
func TestROTGood(t *testing.T) {
|
||||
prog := makeProgram(ROT)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(1)
|
||||
vm.estack.PushVal(2)
|
||||
vm.estack.PushVal(3)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
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)
|
||||
}
|
||||
|
||||
func TestXTUCKbadNoitem(t *testing.T) {
|
||||
prog := makeProgram(XTUCK)
|
||||
vm := load(prog)
|
||||
|
@ -658,6 +813,15 @@ func TestXTUCKbadNegative(t *testing.T) {
|
|||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
}
|
||||
|
||||
func TestXTUCKbadZero(t *testing.T) {
|
||||
prog := makeProgram(XTUCK)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(1)
|
||||
vm.estack.PushVal(0)
|
||||
vm.Run()
|
||||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
}
|
||||
|
||||
func TestXTUCKgood(t *testing.T) {
|
||||
prog := makeProgram(XTUCK)
|
||||
topelement := 5
|
||||
|
@ -745,6 +909,41 @@ func TestOVERgood(t *testing.T) {
|
|||
assert.Equal(t, 3, vm.estack.Len())
|
||||
}
|
||||
|
||||
func TestNIPBadNoItem(t *testing.T) {
|
||||
prog := makeProgram(NIP)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(1)
|
||||
vm.Run()
|
||||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
}
|
||||
|
||||
func TestNIPGood(t *testing.T) {
|
||||
prog := makeProgram(NIP)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(1)
|
||||
vm.estack.PushVal(2)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func TestDROPBadNoItem(t *testing.T) {
|
||||
prog := makeProgram(DROP)
|
||||
vm := load(prog)
|
||||
vm.Run()
|
||||
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||
}
|
||||
|
||||
func TestDROPGood(t *testing.T) {
|
||||
prog := makeProgram(DROP)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(1)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 0, vm.estack.Len())
|
||||
}
|
||||
|
||||
func TestXDROPbadNoitem(t *testing.T) {
|
||||
prog := makeProgram(XDROP)
|
||||
vm := load(prog)
|
||||
|
@ -1118,7 +1317,7 @@ func TestREVERSEBadNotArray(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestREVERSEGoodOneElem(t *testing.T) {
|
||||
prog := makeProgram(REVERSE)
|
||||
prog := makeProgram(DUP, REVERSE)
|
||||
elements := []int{22}
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(1)
|
||||
|
@ -1132,13 +1331,42 @@ func TestREVERSEGoodOneElem(t *testing.T) {
|
|||
assert.Equal(t, int64(elements[0]), e.Int64())
|
||||
}
|
||||
|
||||
func TestREVERSEGoodStruct(t *testing.T) {
|
||||
eodd := []int{22, 34, 42, 55, 81}
|
||||
even := []int{22, 34, 42, 55, 81, 99}
|
||||
eall := [][]int{eodd, even}
|
||||
|
||||
for _, elements := range eall {
|
||||
prog := makeProgram(DUP, REVERSE)
|
||||
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}})
|
||||
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
func TestREVERSEGood(t *testing.T) {
|
||||
eodd := []int{22, 34, 42, 55, 81}
|
||||
even := []int{22, 34, 42, 55, 81, 99}
|
||||
eall := [][]int{eodd, even}
|
||||
|
||||
for _, elements := range eall {
|
||||
prog := makeProgram(REVERSE)
|
||||
prog := makeProgram(DUP, REVERSE)
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(1)
|
||||
vm.estack.PushVal(elements)
|
||||
|
@ -1190,23 +1418,17 @@ func TestREMOVEBadIndex(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestREMOVEGood(t *testing.T) {
|
||||
prog := makeProgram(REMOVE)
|
||||
prog := makeProgram(DUP, PUSH2, REMOVE)
|
||||
elements := []int{22, 34, 42, 55, 81}
|
||||
reselements := []int{22, 34, 55, 81}
|
||||
vm := load(prog)
|
||||
vm.estack.PushVal(1)
|
||||
vm.estack.PushVal(elements)
|
||||
vm.estack.PushVal(2)
|
||||
vm.Run()
|
||||
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||
assert.Equal(t, 2, vm.estack.Len())
|
||||
a := vm.estack.Peek(0).Array()
|
||||
assert.Equal(t, len(reselements), len(a))
|
||||
for k, v := range reselements {
|
||||
e := a[k].Value().(*big.Int)
|
||||
assert.Equal(t, int64(v), e.Int64())
|
||||
}
|
||||
assert.Equal(t, int64(1), vm.estack.Peek(1).BigInt().Int64())
|
||||
assert.Equal(t, makeStackItem(reselements), vm.estack.Pop().value)
|
||||
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func makeProgram(opcodes ...Instruction) []byte {
|
||||
|
|
Loading…
Reference in a new issue