Merge branch 'vm' into dauTT/vm-implement-Map-Struct-167

This commit is contained in:
Roman Khimov 2019-08-12 12:11:29 +03:00 committed by GitHub
commit eeecbf96bf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 474 additions and 157 deletions

View file

@ -0,0 +1,81 @@
{
"category": "Push",
"name": "PUSHBYTES1",
"tests":
[
{
"name": "Good definition",
"script": "0x0100",
"steps":
[
{
"actions":
[
"StepInto"
],
"result":
{
"state": "Break",
"invocationStack":
[
{
"scriptHash": "0xFBC22D517F38E7612798ECE8E5957CF6C41D8CAF",
"instructionPointer": 2,
"nextInstruction": "RET",
"evaluationStack":
[
{
"type": "ByteArray",
"value": "0x00"
}
]
}
]
}
},
{
"actions":
[
"StepInto"
],
"result":
{
"state": "Halt",
"resultStack":
[
{
"type": "ByteArray",
"value": "0x00"
}
]
}
}
]
},
{
"name": "Wrong definition (without enough length)",
"script": "0x01",
"steps":
[
{
"actions":
[
"StepInto"
],
"result":
{
"state": "Fault",
"invocationStack":
[
{
"scriptHash": "0xC51B66BCED5E4491001BD702669770DCCF440982",
"instructionPointer": 1,
"nextInstruction": "RET"
}
]
}
}
]
}
]
}

View file

@ -0,0 +1,6 @@
## Package VM Interop
This package will use the tests in the neo-vm repo to test interopabilty

View file

@ -0,0 +1,26 @@
package csharpinterop
// VMUnitTest is a struct for capturing the fields in the json files
type VMUnitTest struct {
Category string `json:"category"`
Name string `json:"name"`
Tests []struct {
Name string `json:"name"`
Script string `json:"script"`
Steps []struct {
Actions []string `json:"actions"`
Result struct {
State string `json:"state"`
InvocationStack []struct {
ScriptHash string `json:"scriptHash"`
InstructionPointer int `json:"instructionPointer"`
NextInstruction string `json:"nextInstruction"`
EvaluationStack []struct {
Type string `json:"type"`
Value string `json:"value"`
} `json:"evaluationStack"`
} `json:"invocationStack"`
} `json:"result"`
} `json:"steps"`
} `json:"tests"`
}

View file

@ -115,6 +115,20 @@ func (i *Int) Abs() (*Int, error) {
return b, nil
}
// Lte returns a bool value from the comparison of two integers, a and b.
// value is true if a <= b.
// value is false if a > b.
func (i *Int) Lte(s *Int) bool {
return i.Value().Cmp(s.Value()) != 1
}
// Gte returns a bool value from the comparison of two integers, a and b.
// value is true if a >= b.
// value is false if a < b.
func (i *Int) Gte(s *Int) bool {
return i.Value().Cmp(s.Value()) != -1
}
// Lt returns a bool value from the comparison of two integers, a and b.
// value is true if a < b.
// value is false if a >= b.
@ -133,4 +147,28 @@ func (i *Int) Gt(s *Int) bool {
func (i *Int) Hash() (string, error) {
data := fmt.Sprintf("%T %v", i, i.Value())
return KeyGenerator([]byte(data))
// Min returns the mininum between two integers.
func Min(a *Int, b *Int) *Int {
if a.Lte(b) {
return a
}
return b
}
// Max returns the maximun between two integers.
func Max(a *Int, b *Int) *Int {
if a.Gte(b) {
return a
}
return b
}
// Within returns a bool whose value is true
// iff the value of the integer i is within the specified
// range [a,b) (left-inclusive).
func (i *Int) Within(a *Int, b *Int) bool {
// i >= a && i < b
return i.Gte(a) && i.Lt(b)
}

View file

@ -5,12 +5,17 @@ import "github.com/CityOfZion/neo-go/pkg/vm/stack"
type stackInfo func(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error)
var opFunc = map[stack.Instruction]stackInfo{
stack.MIN: Min,
stack.MAX: Max,
stack.WITHIN: Within,
stack.NUMEQUAL: NumEqual,
stack.NUMNOTEQUAL: NumNotEqual,
stack.BOOLAND: BoolAnd,
stack.BOOLOR: BoolOr,
stack.LT: Lt,
stack.LTE: Lte,
stack.GT: Gt,
stack.GTE: Gte,
stack.SHR: Shr,
stack.SHL: Shl,
stack.INC: Inc,

View file

@ -205,6 +205,54 @@ func NumNotEqual(op stack.Instruction, ctx *stack.Context, istack *stack.Invocat
return NONE, nil
}
// Min pops two integers, a and b, off of the stack and pushes an integer to the stack
// whose value is is the minum between a and b's value.
// Returns an error if either items cannot be casted to an integer
func Min(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
operandA, operandB, err := popTwoIntegers(ctx)
if err != nil {
return FAULT, err
}
res := stack.Min(operandA, operandB)
ctx.Estack.Push(res)
return NONE, nil
}
// Max pops two integers, a and b, off of the stack and pushes an integer to the stack
// whose value is is the maximum between a and b's value.
// Returns an error if either items cannot be casted to an integer
func Max(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
operandA, operandB, err := popTwoIntegers(ctx)
if err != nil {
return FAULT, err
}
res := stack.Max(operandA, operandB)
ctx.Estack.Push(res)
return NONE, nil
}
// Within pops three integers, a, b, and c off of the stack and pushes a boolean to the stack
// whose value is true iff c's value is within b's value (include) and a's value.
// Returns an error if at least one item cannot be casted to an boolean.
func Within(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
a, b, c, err := popThreeIntegers(ctx)
if err != nil {
return FAULT, err
}
res := stack.NewBoolean(c.Within(b, a))
ctx.Estack.Push(res)
return NONE, nil
}
// Abs pops an integer off of the stack and pushes its absolute value onto the stack.
// Returns an error if the popped value is not an integer or if the absolute value cannot be taken
func Abs(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
@ -317,17 +365,36 @@ func Negate(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation,
return NONE, nil
}
func popTwoIntegers(ctx *stack.Context) (*stack.Int, *stack.Int, error) {
operandA, err := ctx.Estack.PopInt()
if err != nil {
return nil, nil, err
}
operandB, err := ctx.Estack.PopInt()
if err != nil {
return nil, nil, err
}
// Lte pops two integers, a and b, off of the stack and pushes a boolean the stack
// whose value is true if a's value is less than or equal to b's value.
// Returns an error if either items cannot be casted to an integer
func Lte(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
return operandA, operandB, nil
operandA, operandB, err := popTwoIntegers(ctx)
if err != nil {
return FAULT, err
}
res := operandB.Lte(operandA)
ctx.Estack.Push(stack.NewBoolean(res))
return NONE, nil
}
// Gte pops two integers, a and b, off of the stack and pushes a boolean the stack
// whose value is true if a's value is greated than or equal to b's value.
// Returns an error if either items cannot be casted to an integer
func Gte(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
operandA, operandB, err := popTwoIntegers(ctx)
if err != nil {
return FAULT, err
}
res := operandB.Gte(operandA)
ctx.Estack.Push(stack.NewBoolean(res))
return NONE, nil
}
// Shl pops two integers, a and b, off of the stack and pushes an integer to the stack
@ -402,6 +469,36 @@ func Gt(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rsta
return NONE, nil
}
func popTwoIntegers(ctx *stack.Context) (*stack.Int, *stack.Int, error) {
operandA, err := ctx.Estack.PopInt()
if err != nil {
return nil, nil, err
}
operandB, err := ctx.Estack.PopInt()
if err != nil {
return nil, nil, err
}
return operandA, operandB, nil
}
func popThreeIntegers(ctx *stack.Context) (*stack.Int, *stack.Int, *stack.Int, error) {
operandA, err := ctx.Estack.PopInt()
if err != nil {
return nil, nil, nil, err
}
operandB, err := ctx.Estack.PopInt()
if err != nil {
return nil, nil, nil, err
}
operandC, err := ctx.Estack.PopInt()
if err != nil {
return nil, nil, nil, err
}
return operandA, operandB, operandC, nil
}
func popTwoByteArrays(ctx *stack.Context) (*stack.ByteArray, *stack.ByteArray, error) {
// Pop first stack item and cast as byte array
ba1, err := ctx.Estack.PopByteArray()

View file

@ -13,9 +13,7 @@ func TestIncOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(20))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a)
@ -26,9 +24,7 @@ func TestIncOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(21), item.Value().Int64())
}
@ -38,9 +34,7 @@ func TestDecOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(20))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a)
@ -51,9 +45,7 @@ func TestDecOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(19), item.Value().Int64())
}
@ -63,13 +55,10 @@ func TestAddOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(20))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(23))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -80,9 +69,7 @@ func TestAddOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(43), item.Value().Int64())
@ -93,13 +80,10 @@ func TestSubOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(30))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(40))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -110,9 +94,7 @@ func TestSubOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(-10), item.Value().Int64())
@ -123,13 +105,10 @@ func TestDivOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(10))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(4))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -140,9 +119,7 @@ func TestDivOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(2), item.Value().Int64())
}
@ -152,13 +129,10 @@ func TestModOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(15))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(4))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -169,9 +143,7 @@ func TestModOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(3), item.Value().Int64())
}
@ -181,9 +153,7 @@ func TestNzOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(20))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a)
@ -194,9 +164,7 @@ func TestNzOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, true, item.Value())
}
@ -206,13 +174,10 @@ func TestMulOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(20))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(20))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -223,9 +188,7 @@ func TestMulOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(400), item.Value().Int64())
}
@ -235,9 +198,7 @@ func TestAbsOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(-20))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a)
@ -248,9 +209,7 @@ func TestAbsOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(20), item.Value().Int64())
}
@ -270,9 +229,7 @@ func TestNotOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, true, item.Value())
}
@ -282,13 +239,10 @@ func TestNumEqual(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(6))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(6))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -299,9 +253,7 @@ func TestNumEqual(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, true, item.Value())
}
@ -311,13 +263,10 @@ func TestNumNotEqual(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(5))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(6))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -328,9 +277,7 @@ func TestNumNotEqual(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, true, item.Value())
}
@ -340,9 +287,7 @@ func TestSignOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(-20))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a)
@ -353,9 +298,7 @@ func TestSignOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(-1), item.Value().Int64())
}
@ -365,9 +308,7 @@ func TestNegateOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(-20))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a)
@ -378,25 +319,78 @@ func TestNegateOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(20), item.Value().Int64())
}
func TestLteOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(10))
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(10))
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
// b is the first item pop.
// a is the second item pop.
// we perform a <= b and place
// the result on top of the evaluation
// stack
v.executeOp(stack.LTE, ctx)
// Stack should have one item
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
assert.Nil(t, err)
assert.Equal(t, true, item.Value())
}
func TestGteOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(10))
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(2))
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
// b is the first item pop.
// a is the second item pop.
// we perform a >= b and place
// the result on top of the evaluation
// stack
v.executeOp(stack.GTE, ctx)
// Stack should have one item
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
assert.Nil(t, err)
assert.Equal(t, true, item.Value())
}
func TestShlOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(2))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(3))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -412,9 +406,7 @@ func TestShlOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(16), item.Value().Int64())
}
@ -424,13 +416,10 @@ func TestShrOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(10))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(2))
if err != nil {
t.Fail()
}
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -446,57 +435,51 @@ func TestShrOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Nil(t, err)
assert.Equal(t, int64(2), item.Value().Int64())
}
func TestBoolAndOp(t *testing.T) {
v := VM{}
v := VM{}
a := stack.NewBoolean(true)
a := stack.NewBoolean(true)
b := stack.NewBoolean(true)
ctx := stack.NewContext([]byte{})
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
v.executeOp(stack.BOOLAND, ctx)
v.executeOp(stack.BOOLAND, ctx)
// Stack should have one item
// Stack should have one item
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
if err != nil {
t.Fail()
}
item, err := ctx.Estack.PopBoolean()
assert.Nil(t, err)
assert.Equal(t, true, item.Value())
assert.Equal(t, true, item.Value())
}
func TestBoolOrOp(t *testing.T) {
func TestBoolOrOp(t *testing.T) {
v := VM{}
v := VM{}
a := stack.NewBoolean(false)
a := stack.NewBoolean(false)
b := stack.NewBoolean(true)
ctx := stack.NewContext([]byte{})
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
v.executeOp(stack.BOOLOR, ctx)
v.executeOp(stack.BOOLOR, ctx)
// Stack should have one item
// Stack should have one item
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
if err != nil {
t.Fail()
}
item, err := ctx.Estack.PopBoolean()
assert.Nil(t, err)
assert.Equal(t, true, item.Value())
assert.Equal(t, true, item.Value())
}
func TestLtOp(t *testing.T) {
@ -504,10 +487,10 @@ func TestLtOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(10))
assert.NoError(t, err)
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(2))
assert.NoError(t, err)
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -523,7 +506,7 @@ func TestLtOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
assert.NoError(t, err)
assert.Nil(t, err)
assert.Equal(t, false, item.Value())
}
@ -533,10 +516,10 @@ func TestGtOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(10))
assert.NoError(t, err)
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(2))
assert.NoError(t, err)
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
@ -552,8 +535,89 @@ func TestGtOp(t *testing.T) {
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
assert.NoError(t, err)
assert.Nil(t, err)
assert.Equal(t, true, item.Value())
}
func TestMinOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(10))
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(2))
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
v.executeOp(stack.MIN, ctx)
// 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(2), item.Value().Int64())
}
func TestMaxOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(10))
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(2))
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b)
v.executeOp(stack.MAX, ctx)
// 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 TestWithinOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(5))
assert.Nil(t, err)
b, err := stack.NewInt(big.NewInt(2))
assert.Nil(t, err)
c, err := stack.NewInt(big.NewInt(10))
assert.Nil(t, err)
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a).Push(b).Push(c)
// c is the first item popped.
// b is the second item popped.
// a is the third item popped.
// if a is within [b, c) we place a boolean,
// whose value is true, on top of the evaluation
// stack. Otherwise we place a boolean with
// false value.
v.executeOp(stack.WITHIN, ctx)
// Stack should have one item
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopBoolean()
assert.Nil(t, err)
assert.Equal(t, true, item.Value())
}