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:
Roman Khimov 2019-09-16 19:46:12 +03:00 committed by GitHub
commit 0838948540
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 323 additions and 64 deletions

View file

@ -121,6 +121,8 @@ func (e *Element) Array() []StackItem {
switch t := e.value.(type) { switch t := e.value.(type) {
case *ArrayItem: case *ArrayItem:
return t.value return t.value
case *StructItem:
return t.value
default: default:
panic("element is not an array") panic("element is not an array")
} }

View file

@ -26,7 +26,7 @@ var binaryExprTestCases = []testCase{
return x return x
} }
`, `,
big.NewInt(0), []byte{},
}, },
{ {
"simple div", "simple div",
@ -86,7 +86,7 @@ var binaryExprTestCases = []testCase{
return 0 return 0
} }
`, `,
big.NewInt(0), []byte{},
}, },
{ {
"compare equal strings with eql", "compare equal strings with eql",
@ -128,7 +128,7 @@ var binaryExprTestCases = []testCase{
return 0 return 0
} }
`, `,
big.NewInt(0), []byte{},
}, },
{ {
"compare equal ints with eql", "compare equal ints with eql",
@ -156,7 +156,7 @@ var binaryExprTestCases = []testCase{
return 0 return 0
} }
`, `,
big.NewInt(0), []byte{},
}, },
{ {
"compare not equal ints with eql", "compare not equal ints with eql",
@ -170,7 +170,7 @@ var binaryExprTestCases = []testCase{
return 0 return 0
} }
`, `,
big.NewInt(0), []byte{},
}, },
{ {
"compare not equal ints with neq", "compare not equal ints with neq",

View file

@ -275,7 +275,7 @@ func TestIfUnaryInvert(t *testing.T) {
return 0 return 0
} }
` `
eval(t, src, big.NewInt(0)) eval(t, src, []byte{})
} }
func TestAppendByte(t *testing.T) { func TestAppendByte(t *testing.T) {

View file

@ -35,7 +35,7 @@ func TestNotAssignedFunctionCall(t *testing.T) {
return 0 return 0
} }
` `
eval(t, src, big.NewInt(0)) eval(t, src, []byte{})
} }
func TestMultipleFunctionCalls(t *testing.T) { func TestMultipleFunctionCalls(t *testing.T) {

View file

@ -30,7 +30,7 @@ func TestGT(t *testing.T) {
return 0 return 0
} }
` `
eval(t, src, big.NewInt(0)) eval(t, src, []byte{})
} }
func TestGTE(t *testing.T) { func TestGTE(t *testing.T) {
@ -44,7 +44,7 @@ func TestGTE(t *testing.T) {
return 0 return 0
} }
` `
eval(t, src, big.NewInt(0)) eval(t, src, []byte{})
} }
func TestLAND(t *testing.T) { func TestLAND(t *testing.T) {
@ -89,5 +89,5 @@ func TestNestedIF(t *testing.T) {
return 0 return 0
} }
` `
eval(t, src, big.NewInt(0)) eval(t, src, []byte{})
} }

View file

@ -32,7 +32,7 @@ func TestImportStruct(t *testing.T) {
return b.Y return b.Y
} }
` `
eval(t, src, big.NewInt(0)) eval(t, src, []byte{})
} }
func TestMultipleDirFileImport(t *testing.T) { func TestMultipleDirFileImport(t *testing.T) {

View file

@ -179,7 +179,7 @@ var structTestCases = []testCase{
return t.y return t.y
} }
`, `,
big.NewInt(0), []byte{},
}, },
{ {
"test return struct from func", "test return struct from func",
@ -209,7 +209,7 @@ var structTestCases = []testCase{
vm.NewBigIntegerItem(1), vm.NewBigIntegerItem(1),
vm.NewBigIntegerItem(2), vm.NewBigIntegerItem(2),
vm.NewByteArrayItem([]byte("hello")), vm.NewByteArrayItem([]byte("hello")),
vm.NewBigIntegerItem(0), vm.NewByteArrayItem([]byte{}),
}, },
}, },
{ {

View file

@ -257,7 +257,7 @@ func (v *VM) execute(ctx *Context, op Instruction) {
v.estack.PushVal(val) v.estack.PushVal(val)
case PUSH0: case PUSH0:
v.estack.PushVal(0) v.estack.PushVal([]byte{})
case PUSHDATA1: case PUSHDATA1:
n := ctx.readByte() n := ctx.readByte()
@ -375,7 +375,7 @@ func (v *VM) execute(ctx *Context, op Instruction) {
case XTUCK: case XTUCK:
n := int(v.estack.Pop().BigInt().Int64()) n := int(v.estack.Pop().BigInt().Int64())
if n < 0 { if n <= 0 {
panic("XTUCK: invalid length") panic("XTUCK: invalid length")
} }
a := v.estack.Dup(0) a := v.estack.Dup(0)
@ -388,21 +388,20 @@ func (v *VM) execute(ctx *Context, op Instruction) {
v.estack.InsertAt(a, n) v.estack.InsertAt(a, n)
case ROT: case ROT:
c := v.estack.Pop() e := v.estack.RemoveAt(2)
b := v.estack.Pop() if e == nil {
a := v.estack.Pop() panic("no top-level element found")
}
v.estack.Push(b) v.estack.Push(e)
v.estack.Push(c)
v.estack.Push(a)
case DEPTH: case DEPTH:
v.estack.PushVal(v.estack.Len()) v.estack.PushVal(v.estack.Len())
case NIP: case NIP:
elem := v.estack.Pop() elem := v.estack.RemoveAt(1)
_ = v.estack.Pop() if elem == nil {
v.estack.Push(elem) panic("no second element found")
}
case OVER: case OVER:
b := v.estack.Pop() b := v.estack.Pop()
@ -441,11 +440,20 @@ func (v *VM) execute(ctx *Context, op Instruction) {
} }
case DROP: case DROP:
if v.estack.Len() < 1 {
panic("stack is too small")
}
v.estack.Pop() v.estack.Pop()
case EQUAL: case EQUAL:
b := v.estack.Pop() b := v.estack.Pop()
if b == nil {
panic("no top-level element found")
}
a := v.estack.Pop() a := v.estack.Pop()
if a == nil {
panic("no second-to-the-top element found")
}
v.estack.PushVal(reflect.DeepEqual(a, b)) v.estack.PushVal(reflect.DeepEqual(a, b))
// Bit operations. // Bit operations.
@ -497,11 +505,17 @@ func (v *VM) execute(ctx *Context, op Instruction) {
case SHL: case SHL:
b := v.estack.Pop().BigInt() b := v.estack.Pop().BigInt()
if b.Int64() == 0 {
return
}
a := v.estack.Pop().BigInt() a := v.estack.Pop().BigInt()
v.estack.PushVal(new(big.Int).Lsh(a, uint(b.Int64()))) v.estack.PushVal(new(big.Int).Lsh(a, uint(b.Int64())))
case SHR: case SHR:
b := v.estack.Pop().BigInt() b := v.estack.Pop().BigInt()
if b.Int64() == 0 {
return
}
a := v.estack.Pop().BigInt() a := v.estack.Pop().BigInt()
v.estack.PushVal(new(big.Int).Rsh(a, uint(b.Int64()))) 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: case NEWARRAY:
item := v.estack.Pop() item := v.estack.Pop()
switch t := item.value.(type) { switch t := item.value.(type) {
case *BigIntegerItem:
n := t.value.Int64()
items := make([]StackItem, n)
v.estack.PushVal(&ArrayItem{items})
case *StructItem: case *StructItem:
v.estack.PushVal(&ArrayItem{t.value}) v.estack.PushVal(&ArrayItem{t.value})
case *ArrayItem: case *ArrayItem:
v.estack.PushVal(t) v.estack.PushVal(t)
default: default:
panic("NEWARRAY: invalid operand") n := item.BigInt()
items := makeArrayOfFalses(int(n.Int64()))
v.estack.PushVal(&ArrayItem{items})
} }
case NEWSTRUCT: case NEWSTRUCT:
item := v.estack.Pop() item := v.estack.Pop()
switch t := item.value.(type) { switch t := item.value.(type) {
case *BigIntegerItem:
n := t.value.Int64()
items := make([]StackItem, n)
v.estack.PushVal(&StructItem{items})
case *ArrayItem: case *ArrayItem:
v.estack.PushVal(&StructItem{t.value}) v.estack.PushVal(&StructItem{t.value})
case *StructItem: case *StructItem:
v.estack.PushVal(t) v.estack.PushVal(t)
default: default:
panic("NEWSTRUCT: invalid operand") n := item.BigInt()
items := makeArrayOfFalses(int(n.Int64()))
v.estack.PushVal(&StructItem{items})
} }
case APPEND: case APPEND:
@ -683,7 +693,12 @@ func (v *VM) execute(ctx *Context, op Instruction) {
item := arr[index] item := arr[index]
v.estack.PushVal(item) v.estack.PushVal(item)
default: 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: case SETITEM:
@ -707,7 +722,7 @@ func (v *VM) execute(ctx *Context, op Instruction) {
} }
case REVERSE: case REVERSE:
a := v.estack.Peek(0).Array() a := v.estack.Pop().Array()
if len(a) > 1 { if len(a) > 1 {
for i, j := 0, len(a)-1; i <= j; i, j = i+1, j-1 { for i, j := 0, len(a)-1; i <= j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i] a[i], a[j] = a[j], a[i]
@ -715,10 +730,25 @@ func (v *VM) execute(ctx *Context, op Instruction) {
} }
case REMOVE: case REMOVE:
key := int(v.estack.Pop().BigInt().Int64()) key := int(v.estack.Pop().BigInt().Int64())
elem := v.estack.Peek(0) elem := v.estack.Pop()
a := elem.Array() switch t := elem.value.(type) {
a = append(a[:key], a[key+1:]...) case *ArrayItem:
elem.value = makeStackItem(a) a := t.value
if key < 0 || key >= len(a) {
panic("REMOVE: invalid index")
}
a = append(a[:key], a[key+1:]...)
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: case ARRAYSIZE:
elem := v.estack.Pop() elem := v.estack.Pop()
@ -735,10 +765,7 @@ func (v *VM) execute(ctx *Context, op Instruction) {
case SIZE: case SIZE:
elem := v.estack.Pop() elem := v.estack.Pop()
arr, ok := elem.value.Value().([]uint8) arr := elem.Bytes()
if !ok {
panic("SIZE: item not of type []uint8")
}
v.estack.PushVal(len(arr)) v.estack.PushVal(len(arr))
case JMP, JMPIF, JMPIFNOT: 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() { func init() {
log.SetPrefix("NEO-GO-VM > ") log.SetPrefix("NEO-GO-VM > ")
log.SetFlags(0) log.SetFlags(0)

View file

@ -283,6 +283,50 @@ func TestSub(t *testing.T) {
assert.Equal(t, int64(2), vm.estack.Pop().BigInt().Int64()) 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) { func TestLT(t *testing.T) {
prog := makeProgram(LT) prog := makeProgram(LT)
vm := load(prog) vm := load(prog)
@ -335,6 +379,32 @@ func TestDepth(t *testing.T) {
assert.Equal(t, int64(3), vm.estack.Pop().BigInt().Int64()) 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) { func TestNumEqual(t *testing.T) {
prog := makeProgram(NUMEQUAL) prog := makeProgram(NUMEQUAL)
vm := load(prog) vm := load(prog)
@ -371,7 +441,7 @@ func TestNEWARRAYInteger(t *testing.T) {
vm.Run() vm.Run()
assert.Equal(t, false, vm.state.HasFlag(faultState)) assert.Equal(t, false, vm.state.HasFlag(faultState))
assert.Equal(t, 1, vm.estack.Len()) 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) { func TestNEWARRAYStruct(t *testing.T) {
@ -396,12 +466,14 @@ func TestNEWARRAYArray(t *testing.T) {
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value) assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
} }
func TestNEWARRAYWrongType(t *testing.T) { func TestNEWARRAYByteArray(t *testing.T) {
prog := makeProgram(NEWARRAY) prog := makeProgram(NEWARRAY)
vm := load(prog) vm := load(prog)
vm.estack.Push(NewElement([]byte{})) vm.estack.PushVal([]byte{})
vm.Run() 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) { func TestNEWSTRUCTInteger(t *testing.T) {
@ -411,7 +483,7 @@ func TestNEWSTRUCTInteger(t *testing.T) {
vm.Run() vm.Run()
assert.Equal(t, false, vm.state.HasFlag(faultState)) assert.Equal(t, false, vm.state.HasFlag(faultState))
assert.Equal(t, 1, vm.estack.Len()) 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) { func TestNEWSTRUCTArray(t *testing.T) {
@ -436,12 +508,14 @@ func TestNEWSTRUCTStruct(t *testing.T) {
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value) assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
} }
func TestNEWSTRUCTWrongType(t *testing.T) { func TestNEWSTRUCTByteArray(t *testing.T) {
prog := makeProgram(NEWSTRUCT) prog := makeProgram(NEWSTRUCT)
vm := load(prog) vm := load(prog)
vm.estack.Push(NewElement([]byte{})) vm.estack.PushVal([]byte{})
vm.Run() 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) { func TestAPPENDArray(t *testing.T) {
@ -488,6 +562,64 @@ func TestAPPENDWrongType(t *testing.T) {
assert.Equal(t, true, vm.state.HasFlag(faultState)) 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) { func TestSIGNNoArgument(t *testing.T) {
prog := makeProgram(SIGN) prog := makeProgram(SIGN)
vm := load(prog) vm := load(prog)
@ -633,6 +765,29 @@ func TestPICKgood(t *testing.T) {
assert.Equal(t, int64(result), vm.estack.Pop().BigInt().Int64()) 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) { func TestXTUCKbadNoitem(t *testing.T) {
prog := makeProgram(XTUCK) prog := makeProgram(XTUCK)
vm := load(prog) vm := load(prog)
@ -658,6 +813,15 @@ func TestXTUCKbadNegative(t *testing.T) {
assert.Equal(t, true, vm.state.HasFlag(faultState)) 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) { func TestXTUCKgood(t *testing.T) {
prog := makeProgram(XTUCK) prog := makeProgram(XTUCK)
topelement := 5 topelement := 5
@ -745,6 +909,41 @@ func TestOVERgood(t *testing.T) {
assert.Equal(t, 3, vm.estack.Len()) 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) { func TestXDROPbadNoitem(t *testing.T) {
prog := makeProgram(XDROP) prog := makeProgram(XDROP)
vm := load(prog) vm := load(prog)
@ -1118,7 +1317,7 @@ func TestREVERSEBadNotArray(t *testing.T) {
} }
func TestREVERSEGoodOneElem(t *testing.T) { func TestREVERSEGoodOneElem(t *testing.T) {
prog := makeProgram(REVERSE) prog := makeProgram(DUP, REVERSE)
elements := []int{22} elements := []int{22}
vm := load(prog) vm := load(prog)
vm.estack.PushVal(1) vm.estack.PushVal(1)
@ -1132,13 +1331,42 @@ func TestREVERSEGoodOneElem(t *testing.T) {
assert.Equal(t, int64(elements[0]), e.Int64()) 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) { func TestREVERSEGood(t *testing.T) {
eodd := []int{22, 34, 42, 55, 81} eodd := []int{22, 34, 42, 55, 81}
even := []int{22, 34, 42, 55, 81, 99} even := []int{22, 34, 42, 55, 81, 99}
eall := [][]int{eodd, even} eall := [][]int{eodd, even}
for _, elements := range eall { for _, elements := range eall {
prog := makeProgram(REVERSE) prog := makeProgram(DUP, REVERSE)
vm := load(prog) vm := load(prog)
vm.estack.PushVal(1) vm.estack.PushVal(1)
vm.estack.PushVal(elements) vm.estack.PushVal(elements)
@ -1190,23 +1418,17 @@ func TestREMOVEBadIndex(t *testing.T) {
} }
func TestREMOVEGood(t *testing.T) { func TestREMOVEGood(t *testing.T) {
prog := makeProgram(REMOVE) prog := makeProgram(DUP, PUSH2, REMOVE)
elements := []int{22, 34, 42, 55, 81} elements := []int{22, 34, 42, 55, 81}
reselements := []int{22, 34, 55, 81} reselements := []int{22, 34, 55, 81}
vm := load(prog) vm := load(prog)
vm.estack.PushVal(1) vm.estack.PushVal(1)
vm.estack.PushVal(elements) vm.estack.PushVal(elements)
vm.estack.PushVal(2)
vm.Run() vm.Run()
assert.Equal(t, false, vm.state.HasFlag(faultState)) assert.Equal(t, false, vm.state.HasFlag(faultState))
assert.Equal(t, 2, vm.estack.Len()) assert.Equal(t, 2, vm.estack.Len())
a := vm.estack.Peek(0).Array() assert.Equal(t, makeStackItem(reselements), vm.estack.Pop().value)
assert.Equal(t, len(reselements), len(a)) assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
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())
} }
func makeProgram(opcodes ...Instruction) []byte { func makeProgram(opcodes ...Instruction) []byte {