Skip to content
This repository has been archived by the owner on Nov 15, 2021. It is now read-only.

Commit

Permalink
add more tests for Map
Browse files Browse the repository at this point in the history
  • Loading branch information
localhuman committed Mar 17, 2018
1 parent b5693bd commit b12a152
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 21 deletions.
11 changes: 2 additions & 9 deletions neo/VM/ExecutionEngine.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ def ExecuteOp(self, opcode, context):

if isinstance(key, CollectionMixin):
# key must be an array index or dictionary key, but not a collection
return self.VM_FAULT_and_report(VMFault.UNKNOWN1, key)
return self.VM_FAULT_and_report(VMFault.KEY_IS_COLLECTION, key)

collection = estack.Pop()

Expand All @@ -693,7 +693,6 @@ def ExecuteOp(self, opcode, context):
estack.PushT(to_pick)

elif isinstance(collection, Map):

success, value = collection.TryGetValue(key)

if success:
Expand All @@ -713,7 +712,7 @@ def ExecuteOp(self, opcode, context):
key = estack.Pop()

if isinstance(key, CollectionMixin):
return self.VM_FAULT_and_report(VMFault.UNKNOWN1)
return self.VM_FAULT_and_report(VMFault.KEY_IS_COLLECTION)

collection = estack.Pop()

Expand Down Expand Up @@ -752,12 +751,6 @@ def ExecuteOp(self, opcode, context):
elif opcode == NEWMAP:
estack.PushT(Map())

# keysItem = estack.Pop()
# valuesItem = estack.Pop()
# if not keysItem.IsArray or not valuesItem.IsArray:
# return self.VM_FAULT_and_report(VMFault.POP_ITEM_NOT_ARRAY, keysItem, valuesItem)
# estack.PushT(Struct([keysItem, valuesItem]))

elif opcode == APPEND:
newItem = estack.Pop()

Expand Down
2 changes: 2 additions & 0 deletions neo/VM/VMFault.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class VMFault(Enum):

DICT_KEY_ERROR = auto()

KEY_IS_COLLECTION = auto()

THROW = auto()
THROWIFNOT = auto()
UNKNOWN_OPCODE = auto()
Empty file added neo/VM/tests/__init__.py
Empty file.
38 changes: 38 additions & 0 deletions neo/VM/tests/test_execution_engine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from unittest import TestCase
from neo.VM.InteropService import *
from neo.VM.ExecutionEngine import ExecutionEngine
from neo.VM.ExecutionEngine import ExecutionContext
from neo.VM import OpCode


class VMTestCase(TestCase):

engine = None
econtext = None

def setUp(self):

self.engine = ExecutionEngine()
self.econtext = ExecutionContext()

def test_add_operations(self):

self.engine.EvaluationStack.PushT(StackItem.New(2))
self.engine.EvaluationStack.PushT(StackItem.New(3))

self.engine.ExecuteOp(OpCode.ADD, self.econtext)

self.assertEqual(len(self.engine.EvaluationStack.Items), 1)

self.assertEqual(self.engine.EvaluationStack.Items[0], StackItem.New(5))

def test_sub_operations(self):

self.engine.EvaluationStack.PushT(StackItem.New(2))
self.engine.EvaluationStack.PushT(StackItem.New(3))

self.engine.ExecuteOp(OpCode.SUB, self.econtext)

self.assertEqual(len(self.engine.EvaluationStack.Items), 1)

self.assertEqual(self.engine.EvaluationStack.Items[0], StackItem.New(-1))
163 changes: 151 additions & 12 deletions neo/VM/tests/test_interop_map.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
from unittest import TestCase
from neo.VM.InteropService import *
from neo.VM.ExecutionEngine import ExecutionEngine
from neo.VM.ExecutionContext import ExecutionContext
from neo.VM import OpCode
from neo.VM import VMState
from mock import patch


class StringIn(str):
def __eq__(self, other):
return self in other


class InteropTest(TestCase):

def test_map1(self):
engine = None
econtext = None

def setUp(self):

self.engine = ExecutionEngine()
self.econtext = ExecutionContext()

def test_interop_map1(self):

map = Map()

Expand All @@ -14,24 +32,21 @@ def test_map1(self):
map.SetItem(Integer(BigInteger(3)), ByteArray(b'abc'))

self.assertEqual(map.Keys, [Integer(BigInteger(3))])

self.assertEqual(map.Values, [ByteArray(b'abc')])

def test_map2(self):
def test_interop_map2(self):

map = Map({'a': 1, 'b': 2, 'c': 3})

self.assertEqual(map.Count, 3)

self.assertEqual(map.ContainsKey('a'), True)

self.assertEqual(map.Contains('a'), False)

map.Clear()

self.assertEqual(map.GetMap(), {})

def test_map3(self):
def test_interop_map3(self):

map = Map({'a': 1, 'b': 2, 'c': 3})

Expand All @@ -46,19 +61,143 @@ def test_map3(self):
map2 = Map({'a': 1, 'b': 2, 'c': 3})

self.assertEqual(map, map2)

self.assertTrue(map.Remove('a'), True)

self.assertEqual(map.Count, 2)

self.assertNotEqual(map, map2)

self.assertEqual(map.TryGetValue('b'), (True, 2))

self.assertEqual(map.TryGetValue('h'), (False, None))

map.SetItem('h', 9)

self.assertEqual(map.GetItem('h'), 9)

self.assertEqual(map.GetMap(), {'b': 2, 'c': 3, 'h': 9})

def test_op_map1(self):

self.engine.ExecuteOp(OpCode.NEWMAP, self.econtext)

self.assertEqual(len(self.engine.EvaluationStack.Items), 1)
self.assertIsInstance(self.engine.EvaluationStack.Items[0], Map)
self.assertEqual(self.engine.EvaluationStack.Items[0].GetMap(), {})

def test_op_map2(self):

self.engine.ExecuteOp(OpCode.NEWMAP, self.econtext)
self.engine.EvaluationStack.PushT(StackItem.New('mykey'))
self.engine.EvaluationStack.PushT(StackItem.New('myVal'))
self.engine.ExecuteOp(OpCode.SETITEM, self.econtext)

self.assertEqual(len(self.engine.EvaluationStack.Items), 0)

def test_op_map3(self):

# set item should fail if not enough things on estack

self.engine.EvaluationStack.PushT(StackItem.New('myvalue'))
self.engine.EvaluationStack.PushT(StackItem.New('mykey'))

with self.assertRaises(Exception) as context:
self.engine.ExecuteOp(OpCode.SETITEM, self.econtext)

self.assertEqual(len(self.engine.EvaluationStack.Items), 0)
self.assertEqual(self.engine.State, VMState.BREAK)

@patch('logzero.logger.error')
def test_op_map4(self, mocked_logger):

# set item should fail if these are out of order
self.engine.EvaluationStack.PushT(StackItem.New('mykey'))
self.engine.ExecuteOp(OpCode.NEWMAP, self.econtext)
self.engine.EvaluationStack.PushT(StackItem.New('myVal'))
self.engine.ExecuteOp(OpCode.SETITEM, self.econtext)

self.assertEqual(self.engine.State, VMState.FAULT | VMState.BREAK)

mocked_logger.assert_called_with(StringIn('VMFault.KEY_IS_COLLECTION'))

@patch('logzero.logger.error')
def test_op_map5(self, mocked_logger):

# set item should fail if these are out of order
self.engine.EvaluationStack.PushT(StackItem.New('mykey'))
self.engine.EvaluationStack.PushT(StackItem.New('mykey'))
self.engine.EvaluationStack.PushT(StackItem.New('myVal'))
self.engine.ExecuteOp(OpCode.SETITEM, self.econtext)

self.assertEqual(self.engine.State, VMState.FAULT | VMState.BREAK)

mocked_logger.assert_called_with(StringIn('VMFault.SETITEM_INVALID_TYPE'))

@patch('logzero.logger.error')
def test_op_map6(self, mocked_logger):
# we can pick an item from a dict
self.engine.EvaluationStack.PushT(Map(dict={StackItem.New('a'): StackItem.New(4)}))
self.engine.EvaluationStack.PushT(StackItem.New('a'))
self.engine.ExecuteOp(OpCode.PICKITEM, self.econtext)

self.assertEqual(len(self.engine.EvaluationStack.Items), 1)
self.assertEqual(self.engine.EvaluationStack.Items[0].GetBigInteger(), 4)

@patch('logzero.logger.error')
def test_op_map7(self, mocked_logger):
# pick item with key is collection causes error
self.engine.EvaluationStack.PushT(Map(dict={StackItem.New('a'): StackItem.New(4)}))
self.engine.EvaluationStack.PushT(Map(dict={StackItem.New('a'): StackItem.New(4)}))
self.engine.ExecuteOp(OpCode.PICKITEM, self.econtext)

self.assertEqual(self.engine.State, VMState.FAULT | VMState.BREAK)

mocked_logger.assert_called_with(StringIn('VMFault.KEY_IS_COLLECTION'))

@patch('logzero.logger.error')
def test_op_map7(self, mocked_logger):
# pick item on non collection causes error
self.engine.EvaluationStack.PushT(StackItem.New('a'))
self.engine.EvaluationStack.PushT(StackItem.New('a'))
self.engine.ExecuteOp(OpCode.PICKITEM, self.econtext)

self.assertEqual(self.engine.State, VMState.FAULT | VMState.BREAK)

mocked_logger.assert_called_with(StringIn('Cannot access item at index') and StringIn('Item is not an array or dict'))

@patch('logzero.logger.error')
def test_op_map9(self, mocked_logger):
# pick item key not found
self.engine.EvaluationStack.PushT(Map(dict={StackItem.New('a'): StackItem.New(4)}))
self.engine.EvaluationStack.PushT(StackItem.New('b'))
self.engine.ExecuteOp(OpCode.PICKITEM, self.econtext)

self.assertEqual(self.engine.State, VMState.FAULT | VMState.BREAK)

mocked_logger.assert_called_with(StringIn('VMFault.DICT_KEY_NOT_FOUND'))

def test_op_map10(self):
# pick item key not found
self.engine.EvaluationStack.PushT(Map(dict={StackItem.New('a'): StackItem.New(4), StackItem.New('b'): StackItem.New(5)}))
self.engine.ExecuteOp(OpCode.KEYS, self.econtext)

self.assertIsInstance(self.engine.EvaluationStack.Items[0], Array)
items = self.engine.EvaluationStack.Items[0].GetArray()
self.assertEqual(items, [StackItem.New('a'), StackItem.New('b')])

def test_op_map11(self):
self.engine.EvaluationStack.PushT(Map(dict={StackItem.New('a'): StackItem.New(4), StackItem.New('b'): StackItem.New(5)}))
self.engine.ExecuteOp(OpCode.VALUES, self.econtext)

self.assertIsInstance(self.engine.EvaluationStack.Items[0], Array)
items = self.engine.EvaluationStack.Items[0].GetArray()
self.assertEqual(items, [StackItem.New(4), StackItem.New(5)])

def test_op_map12(self):
self.engine.EvaluationStack.PushT(Map(dict={StackItem.New('a'): StackItem.New(4), StackItem.New('b'): StackItem.New(5)}))
self.engine.EvaluationStack.PushT(StackItem.New('b'))
self.engine.ExecuteOp(OpCode.HASKEY, self.econtext)

self.assertEqual(self.engine.EvaluationStack.Items[0].GetBoolean(), True)

def test_op_map13(self):
self.engine.EvaluationStack.PushT(Map(dict={StackItem.New('a'): StackItem.New(4), StackItem.New('b'): StackItem.New(5)}))
self.engine.EvaluationStack.PushT(StackItem.New('c'))
self.engine.ExecuteOp(OpCode.HASKEY, self.econtext)

self.assertEqual(self.engine.EvaluationStack.Items[0].GetBoolean(), False)

0 comments on commit b12a152

Please sign in to comment.