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))
Exemple #2
0
    def Runtime_Log(self, engine: ExecutionEngine):
        item = engine.CurrentContext.EvaluationStack.Pop()
        # will raise an exception for types that don't support it
        item.GetByteArray()

        # if we pass we can call the convenience method to pretty print the data
        message = item.GetString()

        hash = UInt160(data=engine.CurrentContext.ScriptHash())

        tx_hash = None

        if engine.ScriptContainer:
            tx_hash = engine.ScriptContainer.Hash
        engine.write_log(str(message))

        # Build and emit smart contract event
        self.events_to_dispatch.append(
            SmartContractEvent(SmartContractEvent.RUNTIME_LOG,
                               ContractParameter(ContractParameterType.String,
                                                 value=message),
                               hash,
                               GetBlockchain().Height + 1,
                               tx_hash,
                               test_mode=engine.testMode))

        return True
Exemple #3
0
def execute_test(data: dict):
    global test_count, skipped_test_count
    for test in data['tests']:
        test_count += 1
        # interop service
        service = InteropService.InteropService()

        # message provider
        script_container = None

        message = test.get("message", None)
        if message:
            script_container = MessageProvider(message)

        # prepare script table
        script_table = None  # there are currently no tests that load a script table so I don't know the format or key value they'll use

        # create engine and run
        engine = ExecutionEngine(crypto=Crypto.Default(), service=service, container=script_container, table=script_table, exit_on_error=True)

        # TODO: should enforce 0x<data> rule in the JSON test case
        if test['script'].startswith('0x'):
            script = test['script'][2:]
        else:
            script = test['script']
        try:
            script = binascii.unhexlify(script)
        except binascii.Error:
            print(f"Skipping test {data['category']}-{data['name']}, cannot read script data")
            test_count -= 1
            skipped_test_count += 1
            continue

        engine.LoadScript(script)

        steps = test.get('steps', None)
        if steps is None:
            continue

        for i, step in enumerate(steps):
            actions = step.get('actions', [])
            for action in actions:
                if action == "StepInto":
                    engine.StepInto()
                elif action == "Execute":
                    engine.Execute()
                elif action == "StepOver":
                    raise ValueError("StepOver not supported!")
                elif action == "StepOut":
                    raise ValueError("StepOut not supported!")

            test_name = test.get("name", "")
            msg = f"{data['category']}-{data['name']}-{test_name}-{i}"
            assert_result(engine, step['result'], msg)
class TestVMErrors(BoaTest):
    engine = ExecutionEngine()
    script = None

    @classmethod
    def setUpClass(cls):
        super(TestVMErrors, cls).setUpClass()
        output = Compiler.instance().load('%s/sc_vm_errors.py' %
                                          os.path.dirname(__file__)).default
        cls.script = output.write()
        settings.set_loglevel(DEBUG)

    @patch('logzero.logger.error')
    def test_invalid_array_index(self, mocked_logger):
        tx, results, total_ops, engine = TestBuild(self.script,
                                                   [1, ['my_arg0']],
                                                   self.GetWallet1(), '0210',
                                                   '07')
        mocked_logger.assert_called_with(
            StringIn('Array index') and StringIn('exceeds list length'))

    @patch('logzero.logger.error')
    def test_negative_array_indexing(self, mocked_logger):
        tx, results, total_ops, engine = TestBuild(self.script,
                                                   [2, ['my_arg0']],
                                                   self.GetWallet1(), '0210',
                                                   '07')
        mocked_logger.assert_called_with(
            StringIn("Array index is less than zero"))

    @patch('logzero.logger.error')
    def test_invalid_type_indexing(self, mocked_logger):
        tx, results, total_ops, engine = TestBuild(self.script,
                                                   [3, ['my_arg0']],
                                                   self.GetWallet1(), '0210',
                                                   '07')
        mocked_logger.assert_called_with(
            StringIn("Cannot access item at index")
            and StringIn("Item is not an array or dict but of type"))

    @patch('logzero.logger.error')
    def test_invalid_appcall(self, mocked_logger):
        tx, results, total_ops, engine = TestBuild(self.script,
                                                   [4, ['my_arg0']],
                                                   self.GetWallet1(),
                                                   '0210',
                                                   '07',
                                                   dynamic=True)
        mocked_logger.assert_called_with(
            StringIn("Trying to call an unknown contract"))

    # make sure this test is always last because we change the logging level
    @patch('logzero.logger.error')
    def test_no_logging_if_loglevel_not_debug(self, mocked_logger):
        settings.set_loglevel(INFO)
        tx, results, total_ops, engine = TestBuild(self.script,
                                                   [1, ['my_arg0']],
                                                   self.GetWallet1(), '0210',
                                                   '07')
        self.assertEqual(0, mocked_logger.call_count)
Exemple #5
0
    def Runtime_Log(self, engine: ExecutionEngine):
        message = engine.CurrentContext.EvaluationStack.Pop().GetString()

        hash = UInt160(data=engine.CurrentContext.ScriptHash())

        tx_hash = None

        if engine.ScriptContainer:
            tx_hash = engine.ScriptContainer.Hash
        engine.write_log(str(message))

        # Build and emit smart contract event
        self.events_to_dispatch.append(SmartContractEvent(SmartContractEvent.RUNTIME_LOG,
                                                          ContractParameter(ContractParameterType.String, value=message),
                                                          hash,
                                                          Blockchain.Default().Height + 1,
                                                          tx_hash,
                                                          test_mode=engine.testMode))

        return True
class TestVMErrors(BoaTest):
    engine = ExecutionEngine()
    script = None

    @classmethod
    def setUpClass(cls):
        super(TestVMErrors, cls).setUpClass()
        output = Compiler.instance().load('%s/sc_vm_errors.py' %
                                          os.path.dirname(__file__)).default
        cls.script = output.write()

    @patch('logzero.logger.error')
    def test_invalid_array_index(self, mocked_logger):
        tx, results, total_ops, engine = TestBuild(self.script,
                                                   [1, ['my_arg0']],
                                                   self.GetWallet1(), '0210',
                                                   '07')
        mocked_logger.assert_called_with(
            StringIn('Array index') and StringIn('exceeds list length'))

    @patch('logzero.logger.error')
    def test_negative_array_indexing(self, mocked_logger):
        tx, results, total_ops, engine = TestBuild(self.script,
                                                   [2, ['my_arg0']],
                                                   self.GetWallet1(), '0210',
                                                   '07')
        mocked_logger.assert_called_with(
            StringIn("Attempting to access an array using a negative index"))

    @patch('logzero.logger.error')
    def test_invalid_type_indexing(self, mocked_logger):
        tx, results, total_ops, engine = TestBuild(self.script,
                                                   [3, ['my_arg0']],
                                                   self.GetWallet1(), '0210',
                                                   '07')
        mocked_logger.assert_called_with(
            StringIn("Cannot access item at index")
            and StringIn("Item is not an array but of type"))

    @patch('logzero.logger.error')
    def test_invalid_appcall(self, mocked_logger):
        tx, results, total_ops, engine = TestBuild(self.script,
                                                   [4, ['my_arg0']],
                                                   self.GetWallet1(),
                                                   '0210',
                                                   '07',
                                                   dynamic=True)
        mocked_logger.assert_called_with(
            StringIn("Trying to call an unknown contract"))
Exemple #7
0
class TestVMErrors(BoaTest):
    engine = ExecutionEngine()
    script = None

    @classmethod
    def setUpClass(cls):
        super(TestVMErrors, cls).setUpClass()
        output = Compiler.instance().load('%s/sc_vm_errors.py' % os.path.dirname(__file__)).default
        cls.script = output.write()

    def test_invalid_array_index(self):
        with self.assertLogHandler('vm', DEBUG) as log_context:
            tx, results, total_ops, engine = TestBuild(self.script, [1, ['my_arg0']], self.GetWallet1(), '0210', '07')
            self.assertTrue(len(log_context.output) > 0)
            log_msg = log_context.output[0]
            self.assertTrue("Array index" in log_msg and "exceeds list length" in log_msg)

    def test_negative_array_indexing(self):
        with self.assertLogHandler('vm', DEBUG) as log_context:
            tx, results, total_ops, engine = TestBuild(self.script, [2, ['my_arg0']], self.GetWallet1(), '0210', '07')
            self.assertTrue(len(log_context.output) > 0)
            log_msg = log_context.output[0]
            self.assertTrue("Array index is less than zero" in log_msg)

    def test_invalid_type_indexing(self):
        with self.assertLogHandler('vm', DEBUG) as log_context:
            tx, results, total_ops, engine = TestBuild(self.script, [3, [1]], self.GetWallet1(), '0210', '07')
            self.assertTrue(len(log_context.output) > 0)
            log_msg = log_context.output[0]
            # an index of 1 for an array with length one is out of bounds
            self.assertTrue("Item is not an Array or Map but of type" in log_msg)

    def test_invalid_appcall(self):
        with self.assertLogHandler('vm', DEBUG) as log_context:
            tx, results, total_ops, engine = TestBuild(self.script, [4, ['my_arg0']], self.GetWallet1(), '0210', '07', dynamic=True)
            found = False
            for log_msg in log_context.output:
                if "Trying to call an unknown contract" in log_msg:
                    found = True
                    break
            self.assertTrue(found)

    def test_no_logging_if_loglevel_not_debug(self):
        with self.assertLogHandler('vm', INFO) as log_context:
            tx, results, total_ops, engine = TestBuild(self.script, [1, ['my_arg0']], self.GetWallet1(), '0210', '07')
            self.assertEqual(len(log_context.output), 0)
class TestUnclosedWhileLoop(BoaTest):
    engine = ExecutionEngine()
    script = None

    @classmethod
    def setUpClass(cls):
        super(TestUnclosedWhileLoop, cls).setUpClass()

        # the following script is a simple contract that is basically `while True`

        cls.script = binascii.unhexlify(b'00c56b620000')

    @classmethod
    def tearDownClass(cls):
        super(TestUnclosedWhileLoop, cls).tearDownClass()

    def test_unclosed_loop_script(self):
        with self.assertLogHandler('vm', DEBUG) as log_context:
            tx, results, total_ops, engine = TestBuild(self.script, [], self.GetWallet1(), '', 'ff')
            self.assertTrue(len(log_context.output) > 0)
            self.assertTrue("Too many free operations processed" in log_context.output[0])
class TestUnclosedWhileLoop(BoaTest):
    engine = ExecutionEngine()
    script = None

    @classmethod
    def setUpClass(cls):
        super(TestUnclosedWhileLoop, cls).setUpClass()

        # the following script is a simple contract that is basically `while True`

        cls.script = binascii.unhexlify(b'00c56b620000')
        settings.set_loglevel(DEBUG)

    @classmethod
    def tearDownClass(cls):
        super(TestUnclosedWhileLoop, cls).tearDownClass()
        settings.set_loglevel(INFO)

    @patch('logzero.logger.debug')
    def test_unclosed_loop_script(self, mocked_logger):
        tx, results, total_ops, engine = TestBuild(self.script, [],
                                                   self.GetWallet1(), '', 'ff')
        mocked_logger.assert_called_with(
            StringIn('Too many free operations processed'))
 def setUp(self):
     self.engine = ExecutionEngine()
     self.econtext = ExecutionContext(Script(self.engine.Crypto, b''), 0)
     self.engine.InvocationStack.PushT(self.econtext)
Exemple #11
0
 def setUp(self):
     self.engine = ExecutionEngine()
     self.econtext = ExecutionContext(engine=self.engine)
Exemple #12
0
class InteropTest(TestCase):
    engine = None
    econtext = None

    @classmethod
    def setUpClass(cls):
        super(InteropTest, cls).setUpClass()
        settings.set_loglevel(DEBUG)

    def setUp(self):
        self.engine = ExecutionEngine()
        self.econtext = ExecutionContext(engine=self.engine)

    def test_interop_map1(self):
        map = Map()

        self.assertEqual(map.Keys, [])
        self.assertEqual(map.Values, [])

        map.SetItem(Integer(BigInteger(3)), ByteArray(b'abc'))

        self.assertEqual(map.Keys, [Integer(BigInteger(3))])
        self.assertEqual(map.Values, [ByteArray(b'abc')])

    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_interop_map3(self):
        map = Map({'a': 1, 'b': 2, 'c': 3})

        self.assertEqual(map.GetBoolean(), True)

        with self.assertRaises(Exception) as context:
            map.GetByteArray()

        with self.assertRaises(Exception) as context:
            map.GetBigInteger()

        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.econtext.EvaluationStack.Items), 1)
        self.assertIsInstance(self.econtext.EvaluationStack.Items[0], Map)
        self.assertEqual(self.econtext.EvaluationStack.Items[0].GetMap(), {})

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

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

    def test_op_map3(self):
        # set item should fail if not enough things on estack

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

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

        self.assertEqual(len(self.econtext.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.econtext.EvaluationStack.PushT(StackItem.New('mykey'))
        self.engine.ExecuteOp(OpCode.NEWMAP, self.econtext)
        self.econtext.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.econtext.EvaluationStack.PushT(StackItem.New('mykey'))
        self.econtext.EvaluationStack.PushT(StackItem.New('mykey'))
        self.econtext.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.econtext.EvaluationStack.PushT(
            Map(dict={StackItem.New('a'): StackItem.New(4)}))
        self.econtext.EvaluationStack.PushT(StackItem.New('a'))
        self.engine.ExecuteOp(OpCode.PICKITEM, self.econtext)

        self.assertEqual(len(self.econtext.EvaluationStack.Items), 1)
        self.assertEqual(
            self.econtext.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.econtext.EvaluationStack.PushT(
            Map(dict={StackItem.New('a'): StackItem.New(4)}))
        self.econtext.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_map8(self, mocked_logger):
        # pick item on non collection causes error
        self.econtext.EvaluationStack.PushT(StackItem.New('a'))
        self.econtext.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.econtext.EvaluationStack.PushT(
            Map(dict={StackItem.New('a'): StackItem.New(4)}))
        self.econtext.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.econtext.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.econtext.EvaluationStack.Items[0], Array)
        items = self.econtext.EvaluationStack.Items[0].GetArray()
        self.assertEqual(items, [StackItem.New('a'), StackItem.New('b')])

    def test_op_map11(self):
        self.econtext.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.econtext.EvaluationStack.Items[0], Array)
        items = self.econtext.EvaluationStack.Items[0].GetArray()
        self.assertEqual(items, [StackItem.New(4), StackItem.New(5)])

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

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

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

        self.assertEqual(self.econtext.EvaluationStack.Items[0].GetBoolean(),
                         False)
Exemple #13
0
    def setUp(self):

        self.engine = ExecutionEngine(crypto=Crypto.Default())
        self.econtext = ExecutionContext()
Exemple #14
0
class VMTestCase(TestCase):

    engine = None
    econtext = None

    def setUp(self):

        self.engine = ExecutionEngine(crypto=Crypto.Default())
        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))

    def test_verify_sig(self):

        # push message ( should be hexlified )
        self.engine.EvaluationStack.PushT(StackItem.New(b'616263646566'))

        # sig
        sig = binascii.unhexlify(
            b'cd0ca967d11cea78e25ad16f15dbe77672258bfec59ff3617c95e317acff063a48d35f71aa5ce7d735977412186e1572507d0f4d204c5bcb6c90e03b8b857fbd'
        )
        self.engine.EvaluationStack.PushT(StackItem.New(sig))

        # pubkey
        pubkey = binascii.unhexlify(
            b'036fbcb5e138c1ce5360e861674c03228af735a9114a5b7fb4121b8350129f3ffe'
        )
        self.engine.EvaluationStack.PushT(pubkey)

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

        res = self.engine.EvaluationStack.Pop()
        self.assertEqual(res, StackItem.New(True))

    def test_verify_sig_fail(self):

        # push message ( should be hexlified )
        self.engine.EvaluationStack.PushT(StackItem.New(b'616263646566'))

        # sig
        sig = binascii.unhexlify(
            b'cd0ca967d11cea78e25ad16f15dbe77672258bfec59ff3617c95e317acff063a48d35f71aa5ce7d735977412186e1572507d0f4d204c5bcb6c90e03b8b857fbd'
        )
        self.engine.EvaluationStack.PushT(StackItem.New(sig))

        # pubkey
        pubkey = binascii.unhexlify(
            b'036fbcb5e138c1ce5360e861674c03228af735a9114a5b7fb4121b8350129f3ffd'
        )
        self.engine.EvaluationStack.PushT(pubkey)

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

        res = self.engine.EvaluationStack.Pop()
        self.assertEqual(res, StackItem.New(False))
Exemple #15
0
 def setUp(self):
     self.engine = ExecutionEngine()
     self.econtext = ExecutionContext()
     self.state_reader = StateReader()
Exemple #16
0
class InteropTest(NeoTestCase):
    engine = None
    econtext = None

    @classmethod
    def setUpClass(cls):
        super(InteropTest, cls).setUpClass()

    def setUp(self):
        self.engine = ExecutionEngine()
        self.econtext = ExecutionContext(engine=self.engine)

    def test_interop_map1(self):
        map = Map()

        self.assertEqual(map.Keys, [])
        self.assertEqual(map.Values, [])

        map.SetItem(Integer(BigInteger(3)), ByteArray(b'abc'))

        self.assertEqual(map.Keys, [Integer(BigInteger(3))])
        self.assertEqual(map.Values, [ByteArray(b'abc')])

    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_interop_map3(self):
        map = Map({'a': 1, 'b': 2, 'c': 3})

        self.assertEqual(map.GetBoolean(), True)

        with self.assertRaises(Exception) as context:
            map.GetByteArray()

        with self.assertRaises(Exception) as context:
            map.GetBigInteger()

        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.econtext.EvaluationStack.Items), 1)
        self.assertIsInstance(self.econtext.EvaluationStack.Items[0], Map)
        self.assertEqual(self.econtext.EvaluationStack.Items[0].GetMap(), {})

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

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

    def test_op_map3(self):
        # set item should fail if not enough things on estack

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

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

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

    def test_op_map4(self):
        with self.assertLogHandler('vm', logging.DEBUG) as log_context:
            # set item should fail if these are out of order
            self.econtext.EvaluationStack.PushT(StackItem.New('mykey'))
            self.engine.ExecuteOp(OpCode.NEWMAP, self.econtext)
            self.econtext.EvaluationStack.PushT(StackItem.New('myVal'))
            self.engine.ExecuteOp(OpCode.SETITEM, self.econtext)

            self.assertEqual(self.engine.State, VMState.FAULT)
            self.assertTrue(len(log_context.output) > 0)
            self.assertTrue(
                'VMFault.KEY_IS_COLLECTION' in log_context.output[0])

    def test_op_map5(self):
        # need to set vm logging level to DEBUG or we will immediately exit `VM_FAULT_and_report()`
        with self.assertLogHandler('vm', logging.DEBUG) as log_context:
            # set item should fail if these are out of order
            self.econtext.EvaluationStack.PushT(StackItem.New('mykey'))
            self.econtext.EvaluationStack.PushT(StackItem.New('mykey'))
            self.econtext.EvaluationStack.PushT(StackItem.New('myVal'))
            self.engine.ExecuteOp(OpCode.SETITEM, self.econtext)

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

            self.assertTrue(len(log_context.output) > 0)
            self.assertEqual(log_context.records[0].levelname, 'DEBUG')
            self.assertTrue(
                'VMFault.SETITEM_INVALID_TYPE' in log_context.output[0])

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

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

    def test_op_map7(self):
        with self.assertLogHandler('vm', logging.DEBUG) as log_context:
            # pick item with key is collection causes error
            self.econtext.EvaluationStack.PushT(
                Map(dict={StackItem.New('a'): StackItem.New(4)}))
            self.econtext.EvaluationStack.PushT(
                Map(dict={StackItem.New('a'): StackItem.New(4)}))
            self.engine.ExecuteOp(OpCode.PICKITEM, self.econtext)

            self.assertEqual(self.engine.State, VMState.FAULT)
            self.assertTrue(len(log_context.output) > 0)
            self.assertTrue(
                'VMFault.KEY_IS_COLLECTION' in log_context.output[0])

    def test_op_map8(self):
        with self.assertLogHandler('vm', logging.DEBUG) as log_context:
            # pick item out of bounds
            self.econtext.EvaluationStack.PushT(StackItem.New('a'))
            self.econtext.EvaluationStack.PushT(StackItem.New('a'))
            self.engine.ExecuteOp(OpCode.PICKITEM, self.econtext)

            self.assertTrue(len(log_context.output) > 0)
            log_msg = log_context.output[0]
            expected_msg = "Array index is less than zero or 97 exceeds list length 1"
            self.assertTrue(expected_msg in log_msg)

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

    def test_op_map9(self):
        with self.assertLogHandler('vm', logging.DEBUG) as log_context:
            # pick item key not found
            self.econtext.EvaluationStack.PushT(
                Map(dict={StackItem.New('a'): StackItem.New(4)}))
            self.econtext.EvaluationStack.PushT(StackItem.New('b'))
            self.engine.ExecuteOp(OpCode.PICKITEM, self.econtext)

            self.assertEqual(self.engine.State, VMState.FAULT)
            self.assertTrue(len(log_context.output) > 0)
            self.assertTrue(
                'VMFault.DICT_KEY_NOT_FOUND' in log_context.output[0])

    def test_op_map10(self):
        # pick item key not found
        self.econtext.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.econtext.EvaluationStack.Items[0], Array)
        items = self.econtext.EvaluationStack.Items[0].GetArray()
        self.assertEqual(items, [StackItem.New('a'), StackItem.New('b')])

    def test_op_map11(self):
        self.econtext.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.econtext.EvaluationStack.Items[0], Array)
        items = self.econtext.EvaluationStack.Items[0].GetArray()
        self.assertEqual(items, [StackItem.New(4), StackItem.New(5)])

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

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

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

        self.assertEqual(self.econtext.EvaluationStack.Items[0].GetBoolean(),
                         False)
Exemple #17
0
    def setUp(self):
        self.engine = ExecutionEngine()
        self.econtext = ExecutionContext(Script(self.engine.Crypto, b''), 0)
        self.engine.InvocationStack.PushT(self.econtext)

        self.service = StateMachine(None, None)
 def setUp(self):
     self.engine = ExecutionEngine()
     self.econtext = ExecutionContext(Script(self.engine.Crypto, b''), 0)
     self.engine.InvocationStack.PushT(self.econtext)
     snapshot = GetBlockchain()._db.createSnapshot()
     self.state_reader = StateReader(TriggerType.Application, snapshot)