c1b6738bdb
* VM:Add abstract stack item * VM: Add stackItems; Array, Boolean, Int and ByteArray * VM: Add tests for stack item * VM: first pass at Random Access Stack object * VM: Add Sub, Mul, Mod LSH, RSH * VM: moved test helper functions into separate file * VM: removed helper functions from stack_test.go * Add conversions for bytearray and Int stack items * Add instructions file for vm * - Add guide to stack readme - Add testReadInt64 * Add Builder * Refactor Int, Boolean, ByteArray conversion * Add Context stack Item * Add Invocation stack - convenience RAS * rename testhelper to test_helper * Move opcode file * - Add `Add` OpCode - Add Opcode Function map * - Add test for math `Add` opcode - basic opcode execution * Add popTwoIntegers convenience func * Add `SUB` Opcode * Export Context Read methods - Return errors where failable * - Add `Op` to handleOP func signature - Add PushNBytes OPcode * remove error on NewBoolean - Expose underlying with Getter on Boolean StackItem - Add Equals method for ByteArray * Make Next() method on Context failable, refactor peekContext and Peek * Add ExecuteOp, Step and Run methods on the VM * Add Equal Opcode * Add THROWIFNOT Opcode * Add RET Opcode * Refactor PushNBytes Opcode * refactor Add, Sub to return VMSTATE add popTwoByteArrays helper function * Add basic tests for vm * clarify vm states * Add astack * [VM] Pass ResultStack to the opcode handlers * [VM] refactor handlers to have rstack as argument * [Stack] - Change RemoveCurrentContext for PopCurrentContext - Add CopTo method to stack * [VM] Add Result stack Len check in simple run test * [VM] fix typo * [Peer/Stall] Change seconds to milliseconds in test
119 lines
2.9 KiB
Go
119 lines
2.9 KiB
Go
package vm
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/CityOfZion/neo-go/pkg/vm/stack"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestPushAdd(t *testing.T) {
|
|
builder := stack.NewBuilder()
|
|
|
|
// PUSH TWO NUMBER
|
|
// ADD THEM TOGETHER
|
|
builder.EmitInt(20).EmitInt(34).EmitOpcode(stack.ADD)
|
|
|
|
// Pass program to VM
|
|
vm := NewVM(builder.Bytes())
|
|
|
|
// Execute first OPCODE
|
|
// Should be PUSH(20)
|
|
state, err := vm.step()
|
|
assert.Equal(t, NONE, int(state))
|
|
assert.Nil(t, err)
|
|
|
|
// We should have the number 20 on stack
|
|
ok := peekTopEStackIsValue(t, vm, 20)
|
|
assert.True(t, ok)
|
|
|
|
// Excute second OPCODE
|
|
// Should be PUSH(34)
|
|
state, err = vm.step()
|
|
assert.Equal(t, NONE, int(state))
|
|
assert.Nil(t, err)
|
|
|
|
// We should have the number 34 at the top of the stack
|
|
ok = peekTopEStackIsValue(t, vm, 34)
|
|
assert.True(t, ok)
|
|
|
|
// Excute third OPCODE
|
|
// Should Add both values on the stack
|
|
state, err = vm.step()
|
|
assert.Equal(t, NONE, int(state))
|
|
assert.Nil(t, err)
|
|
|
|
// We should now have one value on the stack
|
|
//It should be equal to 20+34 = 54
|
|
ok = EstackLen(t, vm, 1)
|
|
assert.True(t, ok)
|
|
ok = peekTopEStackIsValue(t, vm, 54)
|
|
assert.True(t, ok)
|
|
|
|
// If we try to step again, we should get a nil error and HALT
|
|
// because we have gone over the instruction pointer
|
|
// error is nil because when there are nomore instructions, the vm
|
|
// will add a RET opcode and return
|
|
state, err = vm.step()
|
|
assert.Equal(t, HALT, int(state))
|
|
assert.Nil(t, err)
|
|
|
|
}
|
|
|
|
func TestSimpleRun(t *testing.T) {
|
|
|
|
// Program pushes 20 and 34 to the stack
|
|
// Adds them together
|
|
// pushes 54 to the stack
|
|
// Checks if result of addition and 54 are equal
|
|
// Faults if not
|
|
|
|
// Push(20)
|
|
// Push(34)
|
|
// Add
|
|
// Push(54)
|
|
// Equal
|
|
//THROWIFNOT
|
|
builder := stack.NewBuilder()
|
|
builder.EmitInt(20).EmitInt(34).EmitOpcode(stack.ADD)
|
|
builder.EmitInt(54).EmitOpcode(stack.EQUAL).EmitOpcode(stack.THROWIFNOT)
|
|
|
|
// Pass program to VM
|
|
vm := NewVM(builder.Bytes())
|
|
|
|
// Runs vm with program
|
|
_, err := vm.Run()
|
|
assert.Nil(t, err)
|
|
|
|
// ResultStack should be nil
|
|
assert.Equal(t, -1, vm.ResultStack.Len())
|
|
|
|
}
|
|
|
|
// returns true if the value at the top of the evaluation stack is a integer
|
|
// and equals the value passed in
|
|
func peekTopEStackIsValue(t *testing.T, vm *VM, value int64) bool {
|
|
item := peakTopEstack(t, vm)
|
|
integer, err := item.Integer()
|
|
assert.Nil(t, err)
|
|
return value == integer.Value().Int64()
|
|
}
|
|
|
|
// peaks the stack item on the top of the evaluation stack
|
|
// if the current context and returns it
|
|
func peakTopEstack(t *testing.T, vm *VM) stack.Item {
|
|
ctx, err := vm.InvocationStack.CurrentContext()
|
|
fmt.Println(err)
|
|
assert.Nil(t, err)
|
|
item, err := ctx.Estack.Peek(0)
|
|
assert.Nil(t, err)
|
|
return item
|
|
}
|
|
|
|
// returns true if the total number of items on the evaluation stack is equal to value
|
|
func EstackLen(t *testing.T, vm *VM, value int) bool {
|
|
ctx, err := vm.InvocationStack.CurrentContext()
|
|
assert.Nil(t, err)
|
|
return value == ctx.Estack.Len()
|
|
}
|