2019-04-08 23:07:15 +00:00
|
|
|
package vm
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/big"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/CityOfZion/neo-go/pkg/vm/stack"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestNopOp(t *testing.T) {
|
|
|
|
|
|
|
|
v := VM{}
|
|
|
|
|
|
|
|
a, err := stack.NewInt(big.NewInt(10))
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
ctx := stack.NewContext([]byte{})
|
|
|
|
ctx.Estack.Push(a)
|
|
|
|
|
2019-08-12 13:25:16 +00:00
|
|
|
_, err = v.executeOp(stack.NOP, ctx)
|
|
|
|
assert.Nil(t, err)
|
2019-04-08 23:07:15 +00:00
|
|
|
|
|
|
|
// Stack should have one item
|
|
|
|
assert.Equal(t, 1, ctx.Estack.Len())
|
|
|
|
|
|
|
|
item, err := ctx.Estack.PopInt()
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
assert.Equal(t, int64(10), item.Value().Int64())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestJmpOp(t *testing.T) {
|
|
|
|
|
|
|
|
v := VM{}
|
|
|
|
|
|
|
|
a, err := stack.NewInt(big.NewInt(10))
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
ctx := stack.NewContext([]byte{5, 0, 2, 3, 4})
|
|
|
|
ctx.Estack.Push(a)
|
|
|
|
|
|
|
|
// ctx.ip = -1
|
|
|
|
// ctx.IP() = ctx.ip + 1
|
|
|
|
assert.Equal(t, 0, ctx.IP())
|
|
|
|
|
|
|
|
// ctx.ip will be set to offset.
|
|
|
|
// offset = ctx.IP() + int(ctx.ReadInt16()) - 3
|
|
|
|
// = 0 + 5 -3 = 2
|
2019-08-12 13:25:16 +00:00
|
|
|
_, err = v.executeOp(stack.JMP, ctx)
|
|
|
|
assert.Nil(t, err)
|
2019-04-08 23:07:15 +00:00
|
|
|
|
|
|
|
// Stack should have one item
|
|
|
|
assert.Equal(t, 1, ctx.Estack.Len())
|
|
|
|
|
|
|
|
// ctx.IP() = ctx.ip + 1
|
|
|
|
assert.Equal(t, 3, ctx.IP())
|
|
|
|
}
|
|
|
|
|
|
|
|
// test JMPIF instruction with true boolean
|
|
|
|
// on top of the stack
|
|
|
|
func TestJmpIfOp1(t *testing.T) {
|
|
|
|
|
|
|
|
v := VM{}
|
|
|
|
|
|
|
|
a := stack.NewBoolean(true)
|
|
|
|
|
|
|
|
ctx := stack.NewContext([]byte{5, 0, 2, 3, 4})
|
|
|
|
ctx.Estack.Push(a)
|
|
|
|
|
|
|
|
// ctx.ip = -1
|
|
|
|
// ctx.IP() = ctx.ip + 1
|
|
|
|
assert.Equal(t, 0, ctx.IP())
|
|
|
|
|
|
|
|
// ctx.ip will be set to offset
|
|
|
|
// because the there is a true boolean
|
|
|
|
// on top of the stack.
|
|
|
|
// offset = ctx.IP() + int(ctx.ReadInt16()) - 3
|
|
|
|
// = 0 + 5 -3 = 2
|
2019-08-12 13:25:16 +00:00
|
|
|
_, err := v.executeOp(stack.JMPIF, ctx)
|
|
|
|
assert.Nil(t, err)
|
2019-04-08 23:07:15 +00:00
|
|
|
|
|
|
|
// Stack should have 0 item
|
|
|
|
assert.Equal(t, 0, ctx.Estack.Len())
|
|
|
|
|
|
|
|
// ctx.IP() = ctx.ip + 1
|
|
|
|
assert.Equal(t, 3, ctx.IP())
|
|
|
|
}
|
|
|
|
|
|
|
|
// test JMPIF instruction with false boolean
|
|
|
|
// on top of the stack
|
|
|
|
func TestJmpIfOp2(t *testing.T) {
|
|
|
|
|
|
|
|
v := VM{}
|
|
|
|
|
|
|
|
a := stack.NewBoolean(false)
|
|
|
|
|
|
|
|
ctx := stack.NewContext([]byte{5, 0, 2, 3, 4})
|
|
|
|
ctx.Estack.Push(a)
|
|
|
|
|
|
|
|
// ctx.ip = -1
|
|
|
|
// ctx.IP() = ctx.ip + 1
|
|
|
|
assert.Equal(t, 0, ctx.IP())
|
|
|
|
|
|
|
|
// nothing will happen because
|
|
|
|
// the value of the boolean on top of the stack
|
|
|
|
// is false
|
2019-08-12 13:25:16 +00:00
|
|
|
_, err := v.executeOp(stack.JMPIF, ctx)
|
|
|
|
assert.Nil(t, err)
|
2019-04-08 23:07:15 +00:00
|
|
|
|
|
|
|
// Stack should have 0 item
|
|
|
|
assert.Equal(t, 0, ctx.Estack.Len())
|
|
|
|
|
|
|
|
// ctx.IP() = ctx.ip + 1
|
|
|
|
assert.Equal(t, 0, ctx.IP())
|
|
|
|
}
|
|
|
|
|
|
|
|
// test JMPIFNOT instruction with true boolean
|
|
|
|
// on top of the stack
|
|
|
|
func TestJmpIfNotOp1(t *testing.T) {
|
|
|
|
|
|
|
|
v := VM{}
|
|
|
|
|
|
|
|
a := stack.NewBoolean(true)
|
|
|
|
|
|
|
|
ctx := stack.NewContext([]byte{5, 0, 2, 3, 4})
|
|
|
|
ctx.Estack.Push(a)
|
|
|
|
|
|
|
|
// ctx.ip = -1
|
|
|
|
// ctx.IP() = ctx.ip + 1
|
|
|
|
assert.Equal(t, 0, ctx.IP())
|
|
|
|
|
|
|
|
// nothing will happen because
|
|
|
|
// the value of the boolean on top of the stack
|
|
|
|
// is true
|
2019-08-12 13:25:16 +00:00
|
|
|
_, err := v.executeOp(stack.JMPIFNOT, ctx)
|
|
|
|
assert.Nil(t, err)
|
2019-04-08 23:07:15 +00:00
|
|
|
|
|
|
|
// Stack should have 0 item
|
|
|
|
assert.Equal(t, 0, ctx.Estack.Len())
|
|
|
|
|
|
|
|
// ctx.IP() = ctx.ip + 1
|
|
|
|
assert.Equal(t, 0, ctx.IP())
|
|
|
|
}
|
|
|
|
|
|
|
|
// test JMPIFNOT instruction with false boolean
|
|
|
|
// on top of the stack
|
|
|
|
func TestJmpIfNotOp2(t *testing.T) {
|
|
|
|
|
|
|
|
v := VM{}
|
|
|
|
|
|
|
|
a := stack.NewBoolean(false)
|
|
|
|
|
|
|
|
ctx := stack.NewContext([]byte{5, 0, 2, 3, 4})
|
|
|
|
ctx.Estack.Push(a)
|
|
|
|
|
|
|
|
// ctx.ip = -1
|
|
|
|
// ctx.IP() = ctx.ip + 1
|
|
|
|
assert.Equal(t, 0, ctx.IP())
|
|
|
|
|
|
|
|
// ctx.ip will be set to offset
|
|
|
|
// because the there is a false boolean
|
|
|
|
// on top of the stack.
|
|
|
|
// offset = ctx.IP() + int(ctx.ReadInt16()) - 3
|
|
|
|
// = 0 + 5 -3 = 2
|
2019-08-12 13:25:16 +00:00
|
|
|
_, err := v.executeOp(stack.JMPIFNOT, ctx)
|
|
|
|
assert.Nil(t, err)
|
2019-04-08 23:07:15 +00:00
|
|
|
|
|
|
|
// Stack should have one item
|
|
|
|
assert.Equal(t, 0, ctx.Estack.Len())
|
|
|
|
|
|
|
|
// ctx.IP() = ctx.ip + 1
|
|
|
|
assert.Equal(t, 3, ctx.IP())
|
|
|
|
}
|