neoneo-go/pkg/vm/vm_test.go
decentralisedkev c1b6738bdb
VM: Add basic vm (#166)
* 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
2019-03-18 21:40:21 +00:00

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()
}