def inner_task(mocker, request): mocker.patch.object(IconScoreInnerTask, "_open") mocker.patch.object(IconScoreInnerTask, "_close") inner_task = IconScoreInnerTask(Mock(spec=IconConfig)) inner_task._thread_flag = request.param icon_service_engine = Mock(spec=IconServiceEngine) inner_task._icon_service_engine = icon_service_engine return inner_task
def _create_inner_task( prep_storage_open, prep_engine_open, iiss_storage_open, iiss_engine_open, load_last_tx_index, rc_db_from_path, db_factory_create_by_name, icx_engine_open, service_engine_load_builtin_scores, service_engine_init_global_value_by_governance_score): state_db = {} rc_db = {} def state_put(self, key, value): state_db[key] = value def state_get(self, key): return state_db.get(key) def rc_put(key, value): rc_db[key] = value def rc_get(key): return rc_db.get(key) context_db = Mock(spec=ContextDatabase) context_db.key_value_db = state_db context_db.get = state_get context_db.put = state_put iiss_mock_db = Mock(spec=KeyValueDatabase) iiss_mock_db.get = rc_get iiss_mock_db.put = rc_put db_factory_create_by_name.return_value = context_db rc_db_from_path.return_value = iiss_mock_db load_last_tx_index.return_value = 0 inner_task = IconScoreInnerTask(IconConfig("", default_icon_config)) # Patches create_by_name to pass creating DB db_factory_create_by_name.assert_called() icx_engine_open.assert_called() service_engine_load_builtin_scores.assert_called() service_engine_init_global_value_by_governance_score.assert_called() # Mocks _init_global_value_by_governance_score # to ignore initializing governance SCORE inner_task._icon_service_engine._init_global_value_by_governance_score = \ service_engine_init_global_value_by_governance_score return inner_task
def test_get_block_info_for_precommit_state(self): block_height = 10 instant_block_hash = create_block_hash() block_hash = create_block_hash() # success case: when input prev write pre-commit data format, block_hash should be None prev_precommit_data_format = { ConstantKeys.BLOCK_HEIGHT: block_height, ConstantKeys.BLOCK_HASH: instant_block_hash } actual_block_height, actual_instant_block_hash, actual_block_hash = \ IconScoreInnerTask._get_block_info_for_precommit_state(prev_precommit_data_format) self.assertEqual(block_height, actual_block_height) self.assertEqual(instant_block_hash, actual_instant_block_hash) self.assertIsNone(actual_block_hash) # success case: when input new write-pre-commit data format, block_hash should be hash new_precommit_data_format = { ConstantKeys.BLOCK_HEIGHT: block_height, ConstantKeys.OLD_BLOCK_HASH: instant_block_hash, ConstantKeys.NEW_BLOCK_HASH: block_hash } actual_block_height, actual_instant_block_hash, actual_block_hash = \ IconScoreInnerTask._get_block_info_for_precommit_state(new_precommit_data_format) self.assertEqual(block_height, actual_block_height) self.assertEqual(instant_block_hash, actual_instant_block_hash) self.assertEqual(block_hash, actual_block_hash) # failure case: when input invalid data format, should raise key error invalid_precommit_data_format = { ConstantKeys.BLOCK_HEIGHT: block_height, ConstantKeys.OLD_BLOCK_HASH: instant_block_hash, } self.assertRaises( KeyError, IconScoreInnerTask._get_block_info_for_precommit_state, invalid_precommit_data_format)
def setUp(self): self.icon_inner_task_open_patcher = patch( 'iconservice.icon_inner_service.IconScoreInnerTask._open') self.icon_inner_task_close_patcher = patch( 'iconservice.icon_inner_service.IconScoreInnerTask._close') _ = self.icon_inner_task_open_patcher.start() _ = self.icon_inner_task_close_patcher.start() IconScoreInnerTask._open = Mock() self.inner_task = IconScoreInnerTask(Mock(spec=IconConfig)) icon_service_engine = Mock(spec=IconServiceEngine) self.inner_task._icon_service_engine = icon_service_engine block = { ConstantKeys.BLOCK_HEIGHT: hex(0), ConstantKeys.BLOCK_HASH: create_block_hash().hex(), ConstantKeys.TIMESTAMP: hex(0), ConstantKeys.PREV_BLOCK_HASH: create_block_hash().hex() } self.mocked_invoke_request = {"block": block, "transactions": []} self.mocked_write_precommit_request = { ConstantKeys.BLOCK_HEIGHT: hex(0), ConstantKeys.BLOCK_HASH: create_block_hash().hex() } self.mocked_query_request = { ConstantKeys.METHOD: "icx_call", ConstantKeys.PARAMS: {} } exception_msg = "non fatal exception" exception_list = [ InvalidBaseTransactionException, IconServiceBaseException, Exception ] self.exception_list = list( map(lambda exception: exception(exception_msg), exception_list))
def generate_inner_task(db_factory_create_by_name, icx_engine_open, service_engine_load_builtin_scores, service_engine_init_global_value_by_governance_score): memory_db = {} def put(self, key, value): memory_db[key] = value def get(self, key): return memory_db.get(key) context_db = Mock(spec=ContextDatabase) context_db.get = get context_db.put = put db_factory_create_by_name.return_value = context_db inner_task = IconScoreInnerTask(IconConfig("", default_icon_config)) # Patches create_by_name to pass creating DB db_factory_create_by_name.assert_called() icx_engine_open.assert_called() service_engine_load_builtin_scores.assert_called() service_engine_init_global_value_by_governance_score.assert_called() # Mocks get_balance so, it returns always 100 icx inner_task._icon_service_engine._icx_engine.get_balance = \ Mock(return_value=100 * 10 ** 18) # Mocks _init_global_value_by_governance_score # to ignore initializing governance SCORE inner_task._icon_service_engine._init_global_value_by_governance_score = \ service_engine_init_global_value_by_governance_score # Ignores icx transfer inner_task._icon_service_engine._icx_engine._transfer = Mock() # Ignores revision inner_task._icon_service_engine._set_revision_to_context = Mock() return inner_task
class TestIconInnerService(unittest.TestCase): def setUp(self): self.icon_inner_task_open_patcher = patch( 'iconservice.icon_inner_service.IconScoreInnerTask._open') self.icon_inner_task_close_patcher = patch( 'iconservice.icon_inner_service.IconScoreInnerTask._close') _ = self.icon_inner_task_open_patcher.start() _ = self.icon_inner_task_close_patcher.start() IconScoreInnerTask._open = Mock() self.inner_task = IconScoreInnerTask(Mock(spec=IconConfig)) icon_service_engine = Mock(spec=IconServiceEngine) self.inner_task._icon_service_engine = icon_service_engine block = { ConstantKeys.BLOCK_HEIGHT: hex(0), ConstantKeys.BLOCK_HASH: create_block_hash().hex(), ConstantKeys.TIMESTAMP: hex(0), ConstantKeys.PREV_BLOCK_HASH: create_block_hash().hex() } self.mocked_invoke_request = {"block": block, "transactions": []} self.mocked_write_precommit_request = { ConstantKeys.BLOCK_HEIGHT: hex(0), ConstantKeys.BLOCK_HASH: create_block_hash().hex() } self.mocked_query_request = { ConstantKeys.METHOD: "icx_call", ConstantKeys.PARAMS: {} } exception_msg = "non fatal exception" exception_list = [ InvalidBaseTransactionException, IconServiceBaseException, Exception ] self.exception_list = list( map(lambda exception: exception(exception_msg), exception_list)) def tearDown(self): self.icon_inner_task_open_patcher.stop() self.icon_inner_task_close_patcher.stop() def test_get_block_info_for_precommit_state(self): block_height = 10 instant_block_hash = create_block_hash() block_hash = create_block_hash() # success case: when input prev write pre-commit data format, block_hash should be None prev_precommit_data_format = { ConstantKeys.BLOCK_HEIGHT: block_height, ConstantKeys.BLOCK_HASH: instant_block_hash } actual_block_height, actual_instant_block_hash, actual_block_hash = \ IconScoreInnerTask._get_block_info_for_precommit_state(prev_precommit_data_format) self.assertEqual(block_height, actual_block_height) self.assertEqual(instant_block_hash, actual_instant_block_hash) self.assertIsNone(actual_block_hash) # success case: when input new write-pre-commit data format, block_hash should be hash new_precommit_data_format = { ConstantKeys.BLOCK_HEIGHT: block_height, ConstantKeys.OLD_BLOCK_HASH: instant_block_hash, ConstantKeys.NEW_BLOCK_HASH: block_hash } actual_block_height, actual_instant_block_hash, actual_block_hash = \ IconScoreInnerTask._get_block_info_for_precommit_state(new_precommit_data_format) self.assertEqual(block_height, actual_block_height) self.assertEqual(instant_block_hash, actual_instant_block_hash) self.assertEqual(block_hash, actual_block_hash) # failure case: when input invalid data format, should raise key error invalid_precommit_data_format = { ConstantKeys.BLOCK_HEIGHT: block_height, ConstantKeys.OLD_BLOCK_HASH: instant_block_hash, } self.assertRaises( KeyError, IconScoreInnerTask._get_block_info_for_precommit_state, invalid_precommit_data_format) def test_fatal_exception_catch_on_invoke(self): # invoke thread: invoke, write_precommit_state, remove_precommit_state # success case: when FatalException having been raised on invoke # should close the icon service after sending error response expected_error_msg = "fatal exception on invoke" expected_error_code = 32001 def mocked_invoke(block, tx_requests, prev_block_generator, prev_block_validators, prev_block_votes, is_block_editable): raise FatalException(expected_error_msg) self.inner_task._icon_service_engine.invoke = mocked_invoke response = self.inner_task._invoke(self.mocked_invoke_request) assert expected_error_code, response['error']['code'] assert expected_error_msg, response['error']['message'] assert self.inner_task._close.called self.inner_task._close.reset_mock() # success case: when other exception having been raised, error response should be returned for exception in self.exception_list: expected_error_msg = exception.args[0] def mocked_invoke(block, tx_requests, prev_block_generator, prev_block_validators, prev_block_votes, is_block_editable): raise exception self.inner_task._icon_service_engine.invoke = mocked_invoke response = self.inner_task._invoke(self.mocked_invoke_request) assert expected_error_msg, response['error']['message'] assert not self.inner_task._close.called self.inner_task._close.reset_mock() def test_fatal_exception_catch_on_write_precommit_state(self): # success case: when FatalException having been raised on write_precommit_state, # should close the icon service after sending error response expected_error_msg = "fatal exception on write_precommit_state" expected_error_code = 32001 def mocked_write_precommit(block_height, instant_block_hash, block_hash): raise FatalException(expected_error_msg) self.inner_task._icon_service_engine.commit = mocked_write_precommit response = self.inner_task._write_precommit_state( self.mocked_write_precommit_request) assert expected_error_code, response['error']['code'] assert expected_error_msg, response['error']['message'] assert self.inner_task._close.called self.inner_task._close.reset_mock() # success case: when other exception having been raised, error response should be returned for exception in self.exception_list: expected_error_msg = exception.args[0] def mocked_write_precommit(block_height, instant_block_hash, block_hash): raise exception self.inner_task._icon_service_engine.invoke = mocked_write_precommit response = self.inner_task._invoke( self.mocked_write_precommit_request) assert expected_error_msg, response['error']['message'] assert not self.inner_task._close.called self.inner_task._close.reset_mock() def test_fatal_exception_catch_on_query_thread(self): # query thread: query # success case: when FatalException having been raised on query, call (inner call), # should not close the icon service expected_error_msg = "fatal exception on query" expected_error_code = 32001 def mocked_query(method, params): raise FatalException(expected_error_msg) self.inner_task._icon_service_engine.query = mocked_query response = self.inner_task._query(self.mocked_query_request) assert expected_error_code, response['error']['code'] assert expected_error_msg, response['error']['message'] assert not self.inner_task._close.called self.inner_task._close.reset_mock() # success case: when other exception having been raised, error response should be returned for exception in self.exception_list: expected_error_msg = exception.args[0] def mocked_query(method, params): raise exception self.inner_task._icon_service_engine.invoke = mocked_query response = self.inner_task._query(self.mocked_query_request) assert expected_error_msg, response['error']['message'] assert not self.inner_task._close.called self.inner_task._close.reset_mock()