From a8fa9c9244ce833d5047cf51478e7dd0b19adb39 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 31 Mar 2020 17:18:13 +0300 Subject: [PATCH] vm: add tests to stack_item.go closes #199 --- pkg/vm/stack_item_test.go | 373 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) diff --git a/pkg/vm/stack_item_test.go b/pkg/vm/stack_item_test.go index 5725b9aad..53dca3752 100644 --- a/pkg/vm/stack_item_test.go +++ b/pkg/vm/stack_item_test.go @@ -1,12 +1,385 @@ package vm import ( + "math/big" "testing" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/stretchr/testify/assert" ) +var makeStackItemTestCases = []struct { + input interface{} + result StackItem +}{ + { + input: int64(3), + result: &BigIntegerItem{value: big.NewInt(3)}, + }, + { + input: int16(3), + result: &BigIntegerItem{value: big.NewInt(3)}, + }, + { + input: 3, + result: &BigIntegerItem{value: big.NewInt(3)}, + }, + { + input: uint8(3), + result: &BigIntegerItem{value: big.NewInt(3)}, + }, + { + input: uint16(3), + result: &BigIntegerItem{value: big.NewInt(3)}, + }, + { + input: uint32(3), + result: &BigIntegerItem{value: big.NewInt(3)}, + }, + { + input: uint64(3), + result: &BigIntegerItem{value: big.NewInt(3)}, + }, + { + input: big.NewInt(3), + result: &BigIntegerItem{value: big.NewInt(3)}, + }, + { + input: []byte{1, 2, 3, 4}, + result: &ByteArrayItem{value: []byte{1, 2, 3, 4}}, + }, + { + input: []byte{}, + result: &ByteArrayItem{value: []byte{}}, + }, + { + input: "bla", + result: &ByteArrayItem{value: []byte("bla")}, + }, + { + input: "", + result: &ByteArrayItem{value: []byte{}}, + }, + { + input: true, + result: &BoolItem{value: true}, + }, + { + input: false, + result: &BoolItem{value: false}, + }, + { + input: []StackItem{&BigIntegerItem{value: big.NewInt(3)}, &ByteArrayItem{value: []byte{1, 2, 3}}}, + result: &ArrayItem{value: []StackItem{&BigIntegerItem{value: big.NewInt(3)}, &ByteArrayItem{value: []byte{1, 2, 3}}}}, + }, + { + input: []int{1, 2, 3}, + result: &ArrayItem{value: []StackItem{&BigIntegerItem{value: big.NewInt(1)}, &BigIntegerItem{value: big.NewInt(2)}, &BigIntegerItem{value: big.NewInt(3)}}}, + }, +} + +var makeStackItemErrorCases = []struct { + input interface{} +}{ + { + input: nil, + }, +} + +func TestMakeStackItem(t *testing.T) { + for _, testCase := range makeStackItemTestCases { + assert.Equal(t, testCase.result, makeStackItem(testCase.input)) + } + for _, errorCase := range makeStackItemErrorCases { + assert.Panics(t, func() { makeStackItem(errorCase.input) }) + } +} + +var stringerTestCases = []struct { + input StackItem + result string +}{ + { + input: NewStructItem([]StackItem{}), + result: "Struct", + }, + { + input: NewBigIntegerItem(3), + result: "BigInteger", + }, + { + input: NewBoolItem(true), + result: "Boolean", + }, + { + input: NewByteArrayItem([]byte{}), + result: "ByteArray", + }, + { + input: NewArrayItem([]StackItem{}), + result: "Array", + }, + { + input: NewMapItem(), + result: "Map", + }, + { + input: NewInteropItem(nil), + result: "InteropItem", + }, +} + +func TestStringer(t *testing.T) { + for _, testCase := range stringerTestCases { + assert.Equal(t, testCase.result, testCase.input.String()) + } +} + +var equalsTestCases = map[string][]struct { + item1 StackItem + item2 StackItem + result bool +}{ + "struct": { + { + item1: NewStructItem(nil), + item2: nil, + result: false, + }, + { + item1: NewStructItem(nil), + item2: NewBigIntegerItem(1), + result: false, + }, + { + item1: NewStructItem(nil), + item2: NewStructItem([]StackItem{NewBigIntegerItem(1)}), + result: false, + }, + { + item1: NewStructItem([]StackItem{NewBigIntegerItem(1)}), + item2: NewStructItem([]StackItem{NewBigIntegerItem(2)}), + result: false, + }, + { + item1: NewStructItem([]StackItem{NewBigIntegerItem(1)}), + item2: NewStructItem([]StackItem{NewBigIntegerItem(1)}), + result: true, + }, + }, + "bigint": { + { + item1: NewBigIntegerItem(2), + item2: nil, + result: false, + }, + { + item1: NewBigIntegerItem(2), + item2: NewBigIntegerItem(2), + result: true, + }, + { + item1: NewBigIntegerItem(2), + item2: NewBoolItem(false), + result: false, + }, + { + item1: NewBigIntegerItem(0), + item2: NewBoolItem(false), + result: false, + }, + { + item1: NewBigIntegerItem(2), + item2: makeStackItem(int32(2)), + result: true, + }, + }, + "bool": { + { + item1: NewBoolItem(true), + item2: nil, + result: false, + }, + { + item1: NewBoolItem(true), + item2: NewBoolItem(true), + result: true, + }, + { + item1: NewBoolItem(true), + item2: NewBigIntegerItem(1), + result: true, + }, + { + item1: NewBoolItem(true), + item2: NewBoolItem(false), + result: false, + }, + { + item1: NewBoolItem(true), + item2: makeStackItem(true), + result: true, + }, + }, + "bytearray": { + { + item1: NewByteArrayItem(nil), + item2: nil, + result: false, + }, + { + item1: NewByteArrayItem([]byte{1, 2, 3}), + item2: NewByteArrayItem([]byte{1, 2, 3}), + result: true, + }, + { + item1: NewByteArrayItem([]byte{1}), + item2: NewBigIntegerItem(1), + result: true, + }, + { + item1: NewByteArrayItem([]byte{1, 2, 3}), + item2: NewByteArrayItem([]byte{1, 2, 4}), + result: false, + }, + { + item1: NewByteArrayItem([]byte{1, 2, 3}), + item2: makeStackItem([]byte{1, 2, 3}), + result: true, + }, + }, + "array": { + { + item1: NewArrayItem(nil), + item2: nil, + result: false, + }, + { + item1: NewArrayItem([]StackItem{&BigIntegerItem{big.NewInt(1)}, &BigIntegerItem{big.NewInt(2)}, &BigIntegerItem{big.NewInt(3)}}), + item2: NewArrayItem([]StackItem{&BigIntegerItem{big.NewInt(1)}, &BigIntegerItem{big.NewInt(2)}, &BigIntegerItem{big.NewInt(3)}}), + result: false, + }, + { + item1: NewArrayItem([]StackItem{&BigIntegerItem{big.NewInt(1)}}), + item2: NewBigIntegerItem(1), + result: false, + }, + { + item1: NewArrayItem([]StackItem{&BigIntegerItem{big.NewInt(1)}, &BigIntegerItem{big.NewInt(2)}, &BigIntegerItem{big.NewInt(3)}}), + item2: NewArrayItem([]StackItem{&BigIntegerItem{big.NewInt(1)}, &BigIntegerItem{big.NewInt(2)}, &BigIntegerItem{big.NewInt(4)}}), + result: false, + }, + }, + "map": { + { + item1: NewMapItem(), + item2: nil, + result: false, + }, + { + item1: NewMapItem(), + item2: NewMapItem(), + result: false, + }, + { + item1: &MapItem{value: map[interface{}]StackItem{"first": NewBigIntegerItem(1), true: NewByteArrayItem([]byte{2})}}, + item2: &MapItem{value: map[interface{}]StackItem{"first": NewBigIntegerItem(1), true: NewByteArrayItem([]byte{2})}}, + result: false, + }, + { + item1: &MapItem{value: map[interface{}]StackItem{"first": NewBigIntegerItem(1), true: NewByteArrayItem([]byte{2})}}, + item2: &MapItem{value: map[interface{}]StackItem{"first": NewBigIntegerItem(1), true: NewByteArrayItem([]byte{3})}}, + result: false, + }, + }, + "interop": { + { + item1: NewInteropItem(nil), + item2: nil, + result: false, + }, + { + item1: NewInteropItem(nil), + item2: NewInteropItem(nil), + result: true, + }, + { + item1: NewInteropItem(2), + item2: NewInteropItem(3), + result: false, + }, + { + item1: NewInteropItem(3), + item2: NewInteropItem(3), + result: true, + }, + }, +} + +func TestEquals(t *testing.T) { + for name, testBatch := range equalsTestCases { + for _, testCase := range testBatch { + t.Run(name, func(t *testing.T) { + assert.Equal(t, testCase.result, testCase.item1.Equals(testCase.item2)) + // Reference equals + assert.Equal(t, true, testCase.item1.Equals(testCase.item1)) + }) + } + } +} + +var marshalJSONTestCases = []struct { + input StackItem + result []byte +}{ + { + input: NewBigIntegerItem(2), + result: []byte(`2`), + }, + { + input: NewBoolItem(true), + result: []byte(`true`), + }, + { + input: NewByteArrayItem([]byte{1, 2, 3}), + result: []byte(`"010203"`), + }, + { + input: &ArrayItem{value: []StackItem{&BigIntegerItem{value: big.NewInt(3)}, &ByteArrayItem{value: []byte{1, 2, 3}}}}, + result: []byte(`[3,"010203"]`), + }, + { + input: &InteropItem{value: 3}, + result: []byte(`3`), + }, +} + +func TestMarshalJSON(t *testing.T) { + var ( + actual []byte + err error + ) + for _, testCase := range marshalJSONTestCases { + switch testCase.input.(type) { + case *BigIntegerItem: + actual, err = testCase.input.(*BigIntegerItem).MarshalJSON() + case *BoolItem: + actual, err = testCase.input.(*BoolItem).MarshalJSON() + case *ByteArrayItem: + actual, err = testCase.input.(*ByteArrayItem).MarshalJSON() + case *ArrayItem: + actual, err = testCase.input.(*ArrayItem).MarshalJSON() + case *InteropItem: + actual, err = testCase.input.(*InteropItem).MarshalJSON() + default: + continue + } + + assert.NoError(t, err) + assert.Equal(t, testCase.result, actual) + } +} + var toContractParameterTestCases = []struct { input StackItem result smartcontract.Parameter