def setUp(self) -> None: self.blockchain_name = 'testblockchain' self.logger = logging.getLogger('dummy') self.blockchain = Blockchain(name=self.blockchain_name, redis=None) self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.dummy_referendum_count, self.dummy_public_prop_count, \ self.dummy_council_prop_count = 10, 10, 10 self.dummy_validator_set_size = 120 self.dummy_referendum_info_ongoing = { 'Ongoing': { 'proposalHash': '0x345jtg8ergfg8df89h9we9t9sd9g9gsd9g9sdfg', 'end': 124143848, 'threshold': 'Supermajorityapproval', 'delay': 11549, 'tally': { 'ayes': '4544545 KSM', 'nayes': '3454 KSM', 'turnout': '4545454454 KSM' } } } self.dummy_referendum_info_finished = { 'Finished': { 'approved': False, 'end': 124143848 } }
def setUp(self) -> None: self.node_name = 'testnode' self.logger = logging.getLogger('dummy') self.downtime_alert_time_interval = \ TestInternalConf.downtime_alert_time_interval self.downtime_alert_time_interval_with_error_margin = \ self.downtime_alert_time_interval + timedelta(seconds=0.5) self.max_missed_blocks_time_interval = \ TestInternalConf.max_missed_blocks_time_interval self.max_missed_blocks_time_interval_with_error_margin = \ self.max_missed_blocks_time_interval + timedelta(seconds=0.5) self.max_missed_blocks_in_time_interval = \ TestInternalConf.max_missed_blocks_in_time_interval self.full_node = Node(name=self.node_name, rpc_url=None, node_type=NodeType.NON_VALIDATOR_FULL_NODE, pubkey=None, network='', redis=None, internal_conf=TestInternalConf) self.validator = Node(name=self.node_name, rpc_url=None, node_type=NodeType.VALIDATOR_FULL_NODE, pubkey=None, network='', redis=None, internal_conf=TestInternalConf) self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel]) self.dummy_exception = DummyException() self.dummy_block_height = -1 self.dummy_block_time = datetime.min + timedelta(days=123) self.dummy_block_time_after_time_interval = \ self.dummy_block_time + \ self.max_missed_blocks_time_interval_with_error_margin self.dummy_missing_validators = -1 self.dummy_voting_power = 1000 self.dummy_no_of_peers = 1000 self.peers_validator_danger_boundary = \ TestInternalConf.validator_peer_danger_boundary self.peers_less_than_validator_danger_boundary = \ self.peers_validator_danger_boundary - 2 self.peers_more_than_validator_danger_boundary = \ self.peers_validator_danger_boundary + 2 self.peers_validator_safe_boundary = \ TestInternalConf.validator_peer_safe_boundary self.peers_less_than_validator_safe_boundary = \ self.peers_validator_safe_boundary - 2 self.peers_more_than_validator_safe_boundary = \ self.peers_validator_safe_boundary + 2 self.peers_full_node_danger_boundary = \ TestInternalConf.full_node_peer_danger_boundary self.peers_less_than_full_node_danger_boundary = \ self.peers_full_node_danger_boundary - 2 self.peers_more_than_full_node_danger_boundary = \ self.peers_full_node_danger_boundary + 2
def setUp(self) -> None: self.alerter_name = 'testalerter' self.logger = logging.getLogger('dummy') self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.par = PeriodicAliveReminder(timedelta(), self.channel_set, None)
def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.wrapper = PolkadotApiWrapper(self.logger, self.api_endpoint) self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.params = {'websocket': self.ws_url}
def setUp(self) -> None: self.alerter_name = 'testalerter' self.logger = logging.getLogger('dummy') self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel]) self.mute_key = TestInternalConf.redis_periodic_alive_reminder_mute_key self.par = PeriodicAliveReminder(timedelta(), self.channel_set, self.mute_key, None)
class TestGitHubMonitorWithoutRedis(unittest.TestCase): def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.monitor_name = 'testmonitor' self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel]) self.repo_name = 'dummy/repository/' self.releases_page = 'dummy.releases.page' self.redis_prefix = TestInternalConf.redis_github_releases_key_prefix self.db = TestInternalConf.redis_test_database self.host = TestUserConf.redis_host self.port = TestUserConf.redis_port self.password = TestUserConf.redis_password self.monitor = GitHubMonitor(self.monitor_name, self.channel_set, self.logger, None, self.repo_name, self.releases_page, self.redis_prefix, TestInternalConf) @patch(GET_JSON_FUNCTION, return_value={ 'message': 'this would be some error message from GitHub' }) def test_monitor_raises_no_alert_if_message_in_return(self, _): self.monitor.monitor() self.assertTrue(self.counter_channel.no_alerts()) self.assertIsNone(self.monitor._prev_no_of_releases) @patch(GET_JSON_FUNCTION, return_value=DUMMY_RELEASES) def test_monitor_raises_no_alert_if_first_time_round(self, _): self.monitor.monitor() self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(len(DUMMY_RELEASES), self.monitor._prev_no_of_releases) @patch(GET_JSON_FUNCTION, return_value=DUMMY_RELEASES) def test_monitor_raises_no_alert_no_of_releases_decreases(self, _): self.monitor._prev_no_of_releases = len(DUMMY_RELEASES) + 1 self.monitor.monitor() self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(len(DUMMY_RELEASES), self.monitor._prev_no_of_releases) @patch(GET_JSON_FUNCTION, return_value=DUMMY_RELEASES) def test_monitor_raises_info_alert_if_no_of_releases_increases(self, _): self.monitor._prev_no_of_releases = len(DUMMY_RELEASES) - 1 self.monitor.monitor() self.assertEqual(1, self.counter_channel.info_count) self.assertEqual(len(DUMMY_RELEASES), self.monitor._prev_no_of_releases)
def setUp(self) -> None: self.alerter_name = 'testalerter' self.logger = logging.getLogger('dummy') self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConfSomeAlertsDisabled) self.dummy_alert = Alert(AlertCode.TestAlert, 'dummy') self.severities_map_bkp = \ TestInternalConfSomeAlertsDisabled.severities_enabled_map.copy() self.alerts_map_bkp = \ TestInternalConfSomeAlertsDisabled.alerts_enabled_map.copy()
def setUp(self) -> None: self.blockchain_name = 'testblockchain' self.logger = logging.getLogger('dummy') self.blockchain = Blockchain(name=self.blockchain_name, redis=None) self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel]) self.dummy_referendum_count, self.dummy_public_prop_count, \ self.dummy_council_prop_count = 10, 10, 10 self.dummy_validator_set_size = 120 self.dummy_referendum_info = {'end': '8568'}
def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.node_name = 'dummy_node' self.wrapper = OasisApiWrapper(self.logger) self.max_time = 15 self.max_time_less = self.max_time - 10 self.max_time_more = self.max_time + 2 self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.params = {'name': self.node_name}
def setUp(self) -> None: self.blockchain_name = 'testblockchain' self.redis_prefix = self.blockchain_name self.logger = logging.getLogger('dummy') self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel]) self.db = TestInternalConf.redis_test_database self.host = TestUserConf.redis_host self.port = TestUserConf.redis_port self.password = TestUserConf.redis_password self.redis = RedisApi(self.logger, self.db, self.host, self.port, self.password) self.redis.delete_all_unsafe() try: self.redis.ping_unsafe() except RedisConnectionError: self.fail('Redis is not online.') self.blockchain = Blockchain(self.blockchain_name, self.redis) self.dummy_referendum_count = 10 self.dummy_council_prop_count = 10 self.dummy_public_prop_count = 10 self.dummy_validator_set_size = 120
def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.monitor_name = 'testblockchainmonitor' self.blockchain_name = 'testblockchain' self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.db = TestInternalConf.redis_test_database self.host = TestUserConf.redis_host self.port = TestUserConf.redis_port self.password = TestUserConf.redis_password self.redis = RedisApi(self.logger, self.db, self.host, self.port, self.password) self.redis.delete_all_unsafe() try: self.redis.ping_unsafe() except RedisConnectionError: self.fail('Redis is not online.') self.data_sources = [] self.blockchain = Blockchain(self.blockchain_name, self.redis) self.polkadot_api_endpoint = 'api_endpoint' self.monitor = BlockchainMonitor(self.monitor_name, self.blockchain, self.channel_set, self.logger, self.redis, self.data_sources, self.polkadot_api_endpoint, TestInternalConf) self.redis_alive_key_timeout = \ TestInternalConf.redis_blockchain_monitor_alive_key_timeout self.alive_key_timeout = \ TestInternalConf.redis_blockchain_monitor_alive_key_timeout
def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.monitor_name = 'testmonitor' self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel]) self.repo_name = 'dummy/repository/' self.releases_page = 'dummy.releases.page' self.redis_prefix = TestInternalConf.redis_github_releases_key_prefix self.db = TestInternalConf.redis_test_database self.host = TestUserConf.redis_host self.port = TestUserConf.redis_port self.password = TestUserConf.redis_password self.redis = RedisApi(self.logger, self.db, self.host, self.port, self.password) self.redis.delete_all_unsafe() try: self.redis.ping_unsafe() except RedisConnectionError: self.fail('Redis is not online.') self.monitor = GitHubMonitor(self.monitor_name, self.channel_set, self.logger, self.redis, self.repo_name, self.releases_page, self.redis_prefix) self.monitor._internal_conf = TestInternalConf
def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.monitor_name = 'testnodemonitor' self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.db = TestInternalConf.redis_test_database self.host = TestUserConf.redis_host self.port = TestUserConf.redis_port self.password = TestUserConf.redis_password self.redis = RedisApi(self.logger, self.db, self.host, self.port, self.password) self.redis.delete_all_unsafe() try: self.redis.ping_unsafe() except RedisConnectionError: self.fail('Redis is not online.') self.node_monitor_max_catch_up_blocks = \ TestInternalConf.node_monitor_max_catch_up_blocks self.node = None self.archive_alerts_disabled = False self.data_sources = [] self.monitor = NodeMonitor(self.monitor_name, self.channel_set, self.logger, self.node_monitor_max_catch_up_blocks, self.redis, self.node, self.archive_alerts_disabled, self.data_sources, TestInternalConf) self.dummy_last_height_checked = 1000 self.redis_alive_key_timeout = \ TestInternalConf.redis_node_monitor_alive_key_timeout
class TestPeriodicWithoutRedis(unittest.TestCase): def setUp(self) -> None: self.alerter_name = 'testalerter' self.logger = logging.getLogger('dummy') self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.par = PeriodicAliveReminder(timedelta(), self.channel_set, None) def test_periodic_alive_reminder_sends_info_alert_if_redis_disabled(self): self.counter_channel.reset() # ignore previous alerts self.par.send_alive_alert() self.assertEqual(self.counter_channel.warning_count, 0) self.assertEqual(self.counter_channel.critical_count, 0) self.assertEqual(self.counter_channel.info_count, 1) self.assertEqual(self.counter_channel.error_count, 0)
def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.monitor_name = 'testmonitor' self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.repo_name = 'dummy/repository/' self.releases_page = 'dummy.releases.page' self.db = TestInternalConf.redis_test_database self.host = TestUserConf.redis_host self.port = TestUserConf.redis_port self.password = TestUserConf.redis_password self.monitor = GitHubMonitor(self.monitor_name, self.channel_set, self.logger, None, self.repo_name, self.releases_page) self.monitor._internal_conf = TestInternalConf
def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.monitor_name = 'testblockchainmonitor' self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.redis = None self.data_sources = [] self.polkadot_api_endpoint = 'api_endpoint' self.dummy_ws_url_1 = "11.22.33.11:9944" self.dummy_ws_url_2 = "11.22.33.12:9944" self.dummy_ws_url_3 = "11.22.33.13:9944" self.dummy_ws_url_4 = "11.22.33.14:9944" self.dummy_node_name_1 = "testnode1" self.dummy_node_name_2 = "testnode2" self.dummy_node_name_3 = "testnode3" self.dummy_node_name_4 = "testnode4" self.dummy_chain_name = "testchain" self.validator_stash_account_address = "DFJGDF8G898fdghb98dg9wetg9we00w" self.dummy_full_node_1 = Node(name=self.dummy_node_name_1, ws_url=self.dummy_ws_url_1, node_type=NodeType.NON_VALIDATOR_FULL_NODE, stash_account_address='', chain=self.dummy_chain_name, redis=None, is_archive_node=True, internal_conf=TestInternalConf) self.dummy_full_node_2 = Node(name=self.dummy_node_name_2, ws_url=self.dummy_ws_url_2, node_type=NodeType.NON_VALIDATOR_FULL_NODE, stash_account_address='', chain=self.dummy_chain_name, redis=None, is_archive_node=True, internal_conf=TestInternalConf) self.dummy_full_node_3 = Node(name=self.dummy_node_name_3, ws_url=self.dummy_ws_url_3, node_type=NodeType.NON_VALIDATOR_FULL_NODE, stash_account_address='', chain=self.dummy_chain_name, redis=None, is_archive_node=True, internal_conf=TestInternalConf) self.dummy_validator_node_1 = Node( name=self.dummy_node_name_4, ws_url=self.dummy_ws_url_4, node_type=NodeType.VALIDATOR_FULL_NODE, stash_account_address=self.validator_stash_account_address, chain=self.dummy_chain_name, redis=None, is_archive_node=False, internal_conf=TestInternalConf) self.dummy_blockchain = Blockchain(self.dummy_chain_name, None) self.monitor = BlockchainMonitor(self.monitor_name, self.dummy_blockchain, self.channel_set, self.logger, self.redis, self.data_sources, self.polkadot_api_endpoint, TestInternalConf) self.dummy_referendum_count = 10 self.dummy_public_prop_count = 10 self.dummy_council_prop_count = 10 self.dummy_validator_set_size = 120
class TestPeriodicWithRedis(unittest.TestCase): def setUp(self) -> None: self.alerter_name = 'testalerter' self.logger = logging.getLogger('dummy') self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel]) self.db = TestInternalConf.redis_test_database self.host = TestUserConf.redis_host self.port = TestUserConf.redis_port self.password = TestUserConf.redis_password self.redis = RedisApi(self.logger, self.db, self.host, self.port, self.password) self.redis.delete_all_unsafe() try: self.redis.ping_unsafe() except RedisConnectionError: self.fail('Redis is not online.') self.mute_key = TestInternalConf.redis_periodic_alive_reminder_mute_key self.par = PeriodicAliveReminder(timedelta(), self.channel_set, self.mute_key, self.redis) def test_periodic_alive_reminder_sends_info_alert_if_no_mute_key(self): self.counter_channel.reset() # ignore previous alerts self.par.send_alive_alert() self.assertEqual(self.counter_channel.warning_count, 0) self.assertEqual(self.counter_channel.critical_count, 0) self.assertEqual(self.counter_channel.info_count, 1) self.assertEqual(self.counter_channel.error_count, 0) def test_periodic_alive_reminder_sends_no_alert_if_mute_key_present(self): hours = timedelta(hours=float(1)) until = str(datetime.now() + hours) self.redis.set_for(self.mute_key, until, hours) self.counter_channel.reset() # ignore previous alerts self.par.send_alive_alert() self.redis.remove(self.mute_key) self.assertEqual(self.counter_channel.warning_count, 0) self.assertEqual(self.counter_channel.critical_count, 0) self.assertEqual(self.counter_channel.info_count, 0) self.assertEqual(self.counter_channel.error_count, 0)
def setUp(self) -> None: self.alerter_name = 'testalerter' self.logger = logging.getLogger('dummy') self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.db = TestInternalConf.redis_test_database self.host = TestUserConf.redis_host self.port = TestUserConf.redis_port self.password = TestUserConf.redis_password self.redis = RedisApi(self.logger, self.db, self.host, self.port, self.password) self.redis.delete_all_unsafe() try: self.redis.ping_unsafe() except RedisConnectionError: self.fail('Redis is not online.') self.par = PeriodicAliveReminder(timedelta(), self.channel_set, self.redis)
class TestNodeMonitorWithoutRedis(unittest.TestCase): def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.monitor_name = 'testnodemonitor' self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.node_monitor_max_catch_up_blocks = \ TestInternalConf.node_monitor_max_catch_up_blocks self.redis = None self.archive_alerts_disabled = False self.data_sources = [] self.chain = 'testchain' self.full_node_name = 'testfullnode' self.full_node_api_url = '123.123.123.11:9944' self.full_node_consensus_key = "ANDSAdisadjasdaANDAsa" self.full_node_tendermint_key = "ASFLNAFIISDANNSDAKKS2313AA" self.full_node_entity_public_key = "a98dabsfkjabfkjabsf9j" self.full_node_staking_address = "asdsasdsdsaasdsdaswwad" self.full_node = Node( self.full_node_name, self.full_node_api_url, None, NodeType.NON_VALIDATOR_FULL_NODE, '', self.chain, None, True, self.full_node_consensus_key, self.full_node_tendermint_key, self.full_node_staking_address, self.full_node_entity_public_key, TestInternalConf) self.full_node_monitor = NodeMonitor( self.monitor_name, self.channel_set, self.logger, self.node_monitor_max_catch_up_blocks, self.redis, self.full_node, self.archive_alerts_disabled, self.data_sources, TestInternalConf) self.validator_name = 'testvalidator' self.validator_api_url = '13.13.14.11:9944' self.validator_consensus_key = "KASDB01923udlakd19sad" self.validator_tendermint_key = "ALSFNF9)901jjelakNALKNDLKA" self.validator_node_public_key = "DFJGDF8G898fdghb98dg9wetg9we00w" self.validator_node_entity_public_key = "s12adsdghas9as0sa9dhnaskdlan" self.validator_node_staking_address = "jujuujsmjmsjmaklzsdjsdnanz" self.validator = Node( self.validator_name, self.validator_api_url, None, NodeType.VALIDATOR_FULL_NODE, self.validator_node_public_key, self.chain, None, True, self.validator_consensus_key, self.validator_tendermint_key, self.validator_node_staking_address, self.validator_node_entity_public_key, TestInternalConf) self.validator_monitor = NodeMonitor( self.monitor_name, self.channel_set, self.logger, self.node_monitor_max_catch_up_blocks, self.redis, self.validator, self.archive_alerts_disabled, self.data_sources, TestInternalConf) self.dummy_last_height_checked = 1000 self.dummy_bonded_balance = scale_to_giga(5) self.dummy_debonding_balance = scale_to_giga(5) self.dummy_shares_balance = scale_to_giga(5) self.dummy_height_to_check = 1000 self.dummy_no_of_peers = 100 self.dummy_is_missing_blocks = False self.dummy_active = True self.dummy_finalized_block_height = 34535 self.dummy_api_url_1 = "11.22.33.11:9944" self.dummy_api_url_2 = "11.22.33.12:9944" self.dummy_api_url_3 = "11.22.33.13:9944" self.dummy_api_url_4 = "11.22.33.14:9944" self.dummy_api_url_5 = "11.22.33.15:9944" self.dummy_node_name_1 = "testnode1" self.dummy_node_name_2 = "testnode2" self.dummy_node_name_3 = "testnode3" self.dummy_node_name_4 = "testnode4" self.dummy_node_name_5 = "testnode5" self.dummy_validator_node_name_2 = "testvalidatornode2" self.dummy_validator_node_name_3 = "testvalidatornode3" self.dummy_node_consensus_key_1 = "consensus_key_1" self.dummy_node_consensus_key_2 = "consensus_key_2" self.dummy_node_consensus_key_3 = "consensus_key_3" self.dummy_node_tendermint_key_1 = "consensus_key_1" self.dummy_node_tendermint_key_2 = "consensus_key_2" self.dummy_node_tendermint_key_3 = "consensus_key_3" self.dummy_node_entity_public_key_1 = "entity_key_1" self.dummy_node_entity_public_key_2 = "entity_key_2" self.dummy_node_entity_public_key_3 = "entity_key_3" self.dummy_node_staking_address_1 = "staking-key_1" self.dummy_node_staking_address_2 = "staking_key_2" self.dummy_node_staking_address_3 = "staking_key_3" self.dummy_full_node_1 = Node( name=self.dummy_node_name_1, api_url=self.dummy_api_url_1, prometheus_endpoint=None, node_type=NodeType.NON_VALIDATOR_FULL_NODE, node_public_key='', chain=self.chain, redis=None, is_archive_node=True, consensus_public_key='', tendermint_address_key='', staking_address='', entity_public_key='', internal_conf=TestInternalConf) self.dummy_full_node_2 = Node( name=self.dummy_node_name_2, api_url=self.dummy_api_url_2, prometheus_endpoint=None, node_type=NodeType.NON_VALIDATOR_FULL_NODE, node_public_key='', chain=self.chain, redis=None, is_archive_node=True, consensus_public_key='', tendermint_address_key='', staking_address='', entity_public_key='', internal_conf=TestInternalConf) self.dummy_full_node_3 = Node( name=self.dummy_node_name_3, api_url=self.dummy_api_url_3, prometheus_endpoint=None, node_type=NodeType.NON_VALIDATOR_FULL_NODE, node_public_key='', chain=self.chain, redis=None, is_archive_node=True, consensus_public_key='', tendermint_address_key='', staking_address='', entity_public_key='', internal_conf=TestInternalConf) self.dummy_full_node_4 = Node( name=self.dummy_node_name_5, api_url=self.dummy_api_url_5, prometheus_endpoint=None, node_type=NodeType.NON_VALIDATOR_FULL_NODE, node_public_key='', chain=self.chain, redis=None, is_archive_node=False, consensus_public_key='', tendermint_address_key='', staking_address='', entity_public_key='', internal_conf=TestInternalConf) self.dummy_take_event_owner = { "escrow": { "take": { "owner": self.dummy_node_entity_public_key_1, "tokens": "2000000000" } } } self.dummy_validator_node_1 = Node( name=self.dummy_node_name_4, api_url=self.dummy_api_url_4, prometheus_endpoint=None, node_type=NodeType.VALIDATOR_FULL_NODE, node_public_key=self.validator_node_public_key, chain=self.chain, redis=None, is_archive_node=True, consensus_public_key=self.dummy_node_consensus_key_1, tendermint_address_key=self.dummy_node_tendermint_key_1, staking_address=self.dummy_node_staking_address_1, entity_public_key=self.dummy_node_entity_public_key_1, internal_conf=TestInternalConf) self.dummy_validator_node_2 = Node( name=self.dummy_validator_node_name_2, api_url=self.dummy_api_url_4, prometheus_endpoint=None, node_type=NodeType.VALIDATOR_FULL_NODE, node_public_key=self.validator_node_public_key, chain=self.chain, redis=None, is_archive_node=True, consensus_public_key=self.dummy_node_consensus_key_2, tendermint_address_key=self.dummy_node_tendermint_key_2, staking_address=self.dummy_node_staking_address_2, entity_public_key=self.dummy_node_entity_public_key_2, internal_conf=TestInternalConf) self.dummy_validator_node_3 = Node( name=self.dummy_validator_node_name_3, api_url=self.dummy_api_url_4, prometheus_endpoint=None, node_type=NodeType.VALIDATOR_FULL_NODE, node_public_key=self.validator_node_public_key, chain=self.chain, redis=None, is_archive_node=True, consensus_public_key=self.dummy_node_consensus_key_3, tendermint_address_key=self.dummy_node_tendermint_key_3, staking_address=self.dummy_node_staking_address_3, entity_public_key=self.dummy_node_entity_public_key_3, internal_conf=TestInternalConf) def test_indirect_monitoring_data_sources_field_set_correctly( self) -> None: self.data_sources = [ self.dummy_full_node_1, self.dummy_full_node_2, self.dummy_full_node_3, self.dummy_full_node_4, self.dummy_validator_node_1 ] test_monitor = NodeMonitor(self.monitor_name, self.channel_set, self.logger, self.node_monitor_max_catch_up_blocks, self.redis, self.validator, self.archive_alerts_disabled, self.data_sources, TestInternalConf) self.assertEqual(test_monitor.indirect_monitoring_data_sources, self.data_sources) def test_archive_monitoring_data_sources_field_set_correctly(self) -> None: self.data_sources = [ self.dummy_full_node_1, self.dummy_full_node_2, self.dummy_full_node_3, self.dummy_full_node_4, self.dummy_validator_node_1 ] test_monitor = NodeMonitor(self.monitor_name, self.channel_set, self.logger, self.node_monitor_max_catch_up_blocks, self.redis, self.validator, self.archive_alerts_disabled, self.data_sources, TestInternalConf) expected_result = [ self.dummy_full_node_1, self.dummy_full_node_2, self.dummy_full_node_3, self.dummy_validator_node_1 ] self.assertEqual(test_monitor.archive_monitoring_data_sources, expected_result) def test_is_catching_up_false_by_default(self) -> None: self.assertFalse(self.validator_monitor.is_catching_up()) def test_is_indirect_monitoring_disabled_true_if_no_data_sources( self) -> None: self.assertTrue(self.validator_monitor.indirect_monitoring_disabled) def test_is_indirect_monitoring_disabled_false_if_data_sources_given( self) -> None: self.data_sources = [self.dummy_full_node_1, self.dummy_full_node_2] test_monitor = NodeMonitor(self.monitor_name, self.channel_set, self.logger, self.node_monitor_max_catch_up_blocks, self.redis, self.validator, self.archive_alerts_disabled, self.data_sources, TestInternalConf) self.assertFalse(test_monitor.indirect_monitoring_disabled) def test_last_height_checked_NONE_by_default(self) -> None: self.assertEqual(NONE, self.validator_monitor.last_height_checked) def test_no_live_archive_node_alert_sent_false_by_default(self) -> None: self.assertFalse( self.validator_monitor.no_live_archive_node_alert_sent) @patch(PING_NODE_FUNCTION, return_value=None) @patch(GET_WEB_SOCKETS_FUNCTION, return_value=["testnode1", "testnode2", "testnode3", "testnode4"]) def test_data_source_chooses_an_online_full_node_connected_to_the_API( self, mock_get_web_sockets, _) -> None: self.dummy_full_node_1.set_as_down(self.channel_set, self.logger) self.dummy_validator_node_1.set_as_down(self.channel_set, self.logger) self.validator_monitor._indirect_monitoring_data_sources = [ self.dummy_full_node_1, self.dummy_validator_node_1, self.dummy_full_node_2, self.dummy_full_node_3 ] mock_get_web_sockets.return_value = [ self.dummy_node_name_1, self.dummy_node_name_4, self.dummy_node_name_3, self.dummy_node_name_5 ] node = self.validator_monitor.data_source_indirect self.assertEqual(node.name, self.dummy_node_name_3) @patch(PING_NODE_FUNCTION, return_value=None) @patch(GET_WEB_SOCKETS_FUNCTION, return_value=["testnode1", "testnode2", "testnode3", "testnode4"]) def test_data_source_chooses_an_online_validator_node_connected_to_the_API( self, mock_get_web_sockets, _) -> None: self.dummy_full_node_1.set_as_down(self.channel_set, self.logger) self.dummy_full_node_2.set_as_down(self.channel_set, self.logger) self.validator_monitor._indirect_monitoring_data_sources = [ self.dummy_full_node_1, self.dummy_validator_node_1, self.dummy_full_node_2, self.dummy_full_node_3 ] mock_get_web_sockets.return_value = [ self.dummy_node_name_1, self.dummy_node_name_4, self.dummy_node_name_3, self.dummy_node_name_5 ] node = self.validator_monitor.data_source_indirect self.assertEqual(node.name, self.dummy_node_name_4) @patch(GET_WEB_SOCKETS_FUNCTION) def test_data_source_indirect_raises_exception_if_no_node_is_eligible_for_choosing( self, mock_get_web_sockets) -> None: self.dummy_full_node_1.set_as_down(self.channel_set, self.logger) self.dummy_full_node_3.set_as_down(self.channel_set, self.logger) self.validator_monitor._indirect_monitoring_data_sources = [ self.dummy_full_node_1, self.dummy_full_node_2, self.dummy_full_node_3, self.dummy_validator_node_1 ] mock_get_web_sockets.return_value = [self.dummy_api_url_1] try: _ = self.validator_monitor.data_source_indirect self.fail('Expected NoLiveNodeConnectedWithAnApiServerException' ' exception to be thrown.') except NoLiveNodeConnectedWithAnApiServerException: pass @patch(PING_NODE_FUNCTION, return_value=None) @patch(GET_WEB_SOCKETS_FUNCTION, return_value=["testnode1", "testnode5"]) def test_data_source_archive_chooses_an_online_archive_full_node_connected_to_the_API( self, mock_get_web_sockets, _) -> None: self.dummy_full_node_1.set_as_down(self.channel_set, self.logger) self.dummy_full_node_3.set_as_down(self.channel_set, self.logger) self.validator_monitor._archive_monitoring_data_sources = [ self.dummy_full_node_1, self.dummy_full_node_2, self.dummy_full_node_3, self.dummy_validator_node_1, self.dummy_full_node_4 ] mock_get_web_sockets.return_value = [ self.dummy_node_name_1, self.dummy_node_name_5 ] node = self.validator_monitor.data_source_archive self.assertEqual(node.name, self.dummy_node_name_5) @patch(PING_NODE_FUNCTION, return_value=None) @patch(GET_WEB_SOCKETS_FUNCTION, return_value=["testnode1", "testnode4", "testnode5"]) def test_data_source_archive_chooses_an_online_archive_validator_node_connected_to_the_API( self, mock_get_web_sockets, _) -> None: self.dummy_full_node_1.set_as_down(self.channel_set, self.logger) self.dummy_full_node_3.set_as_down(self.channel_set, self.logger) self.dummy_full_node_2.set_as_down(self.channel_set, self.logger) self.validator_monitor._archive_monitoring_data_sources = [ self.dummy_full_node_1, self.dummy_full_node_2, self.dummy_full_node_3, self.dummy_validator_node_1, self.dummy_full_node_4 ] mock_get_web_sockets.return_value = [ self.dummy_node_name_1, self.dummy_node_name_4, self.dummy_node_name_5 ] node = self.validator_monitor.data_source_archive self.assertEqual(node.name, self.dummy_node_name_4) @patch(GET_FINALIZED_HEAD_FUNCTION, return_value={"height": "523686"}) @patch(PING_NODE_FUNCTION, return_value="pong") @patch(GET_SYNCING_FUNCTION, return_value="true") @patch(GET_PEERS_FUNCTION, return_value="92") def test_monitor_direct_sets_node_state_to_retrieved_data( self, _1, _2, _3, _4) -> None: self.validator_monitor.monitor_direct() self.assertFalse(self.validator.is_down) self.assertFalse(self.validator.is_syncing) self.assertEqual(self.validator.no_of_peers, 92) self.assertEqual(self.validator.finalized_block_height, 523686) @patch(GET_FINALIZED_HEAD_FUNCTION, return_value={"height": "523686"}) @patch(PING_NODE_FUNCTION, return_value="pong") @patch(GET_SYNCING_FUNCTION, return_value="true") @patch(GET_PEERS_FUNCTION, return_value="92") @patch(PING_NODE_FUNCTION, return_value=None) def test_monitor_direct_connects_node_to_api_if_monitoring_successful( self, _1, _2, _3_, _4, _5) -> None: self.validator.disconnect_from_api(self.channel_set, self.logger) self.assertFalse(self.validator.is_connected_to_api_server) self.counter_channel.reset() self.validator_monitor.monitor_direct() self.assertTrue(self.validator.is_connected_to_api_server) @patch(GET_WEB_SOCKETS_FUNCTION) def test_data_source_archive_raises_exception_if_no_archive_node_is_eligible_for_choosing( self, mock_get_web_sockets) -> None: self.dummy_full_node_1.set_as_down(self.channel_set, self.logger) self.dummy_full_node_3.set_as_down(self.channel_set, self.logger) self.dummy_validator_node_1.set_as_down(self.channel_set, self.logger) self.validator_monitor._archive_monitoring_data_sources = [ self.dummy_full_node_1, self.dummy_full_node_2, self.dummy_full_node_3, self.dummy_validator_node_1 ] mock_get_web_sockets.return_value = [ self.dummy_api_url_1, self.dummy_api_url_5 ] try: _ = self.validator_monitor.data_source_archive self.fail('Expected ' 'NoLiveArchiveNodeConnectedWithAnApiServerException' ' exception to be thrown.') except NoLiveArchiveNodeConnectedWithAnApiServerException: pass def test_status_returns_as_expected_for_validator_monitor(self) -> None: self.validator_monitor._last_height_checked = \ self.dummy_last_height_checked self.validator._bonded_balance = self.dummy_bonded_balance self.validator._debonding_balance = self.dummy_debonding_balance self.validator._shares_balance = self.dummy_shares_balance self.validator._no_of_peers = self.dummy_no_of_peers self.validator._active = self.dummy_active self.validator._finalized_block_height = \ self.dummy_finalized_block_height self.validator._is_missing_blocks = self.dummy_is_missing_blocks expected_output = "bonded_balance={}, debonding_balance={}, " \ "shares_balance={}, "\ "is_syncing=False, " \ "no_of_peers={}, active={}, " \ "finalized_block_height={}, " \ "is_missing_blocks={}, " \ "last_height_checked={}".format( self.dummy_bonded_balance, self.dummy_debonding_balance, self.dummy_shares_balance, self.dummy_no_of_peers, self.dummy_active, self.dummy_finalized_block_height, self.dummy_is_missing_blocks, self.dummy_last_height_checked) self.assertEqual(expected_output, self.validator_monitor.status()) def test_status_returns_as_expected_for_full_node_monitor(self) -> None: self.full_node._no_of_peers = self.dummy_no_of_peers self.full_node._finalized_block_height = \ self.dummy_finalized_block_height expected_output = "bonded_balance={}, debonding_balance={}, " \ "shares_balance={}, " \ "is_syncing=False, " \ "no_of_peers={}, active={}, " \ "finalized_block_height={}, " \ "is_missing_blocks=False" \ .format( None, None, None, self.dummy_no_of_peers, None, self.dummy_finalized_block_height) self.assertEqual(expected_output, self.full_node_monitor.status()) @patch(GET_FINALIZED_HEAD_FUNCTION, return_value={"height": "523686"}) @patch(PING_NODE_FUNCTION, return_value="pong") @patch(GET_SYNCING_FUNCTION, return_value="true") @patch(GET_PEERS_FUNCTION, return_value="92") def test_monitor_direct_sets_node_state_to_retrieved_data( self, _1, _2, _3, _4) -> None: self.validator_monitor.monitor_direct() self.assertFalse(self.validator.is_down) self.assertFalse(self.validator.is_syncing) self.assertEqual(self.validator.no_of_peers, 92) self.assertEqual(self.validator.finalized_block_height, 523686) @patch(GET_FINALIZED_HEAD_FUNCTION, return_value={"height": "523686"}) @patch(PING_NODE_FUNCTION, return_value="pong") @patch(GET_SYNCING_FUNCTION, return_value="true") @patch(GET_PEERS_FUNCTION, return_value="92") def test_monitor_direct_sets_API_as_up_if_monitoring_successful( self, _1, _2, _3, _4) -> None: self.validator_monitor.monitor_direct() self.assertFalse(self.validator_monitor.data_wrapper.is_api_down) @patch(GET_STAKING_EVENTS_BY_HEIGHT_FUNCTION, return_value=None) @patch(GET_STAKING_ACCOUNT_FUNCTION, return_value={ "escrow": { "active": { "balance": "9999999999993" }, "debonding": { "balance": "9999999999993" } } }) @patch(GET_SIGNED_BLOCKS_FUNCTION, return_value={ "signatures": [ { "validator_address": "06140E5B1FE5D72BAA12AED7815A7E19BC7BDABA" }, { "validator_address": "7C87340EFE4BE695E80099AE3B0CAE545381925D" }, { "validator_address": "0D73013810841C092B8ACB1A9646F412B62EE14C" }, ] }) @patch(GET_BLOCK_HEADER_AT_HEIGHT_FUNCTION, return_value={"height": "55666"}) @patch(GET_CONSENSUS_BLOCK_FUNCTION, return_value={"height":"55666", \ "meta": "asndiasbdiabsidjbasjiaslnlasndlkandlkasldknasdlknaskbda"}) @patch(GET_SESSION_VALIDATORS_FUNCTION, return_value=[]) @patch(GET_STAKING_DELEGATIONS_INFO_FUNCTION, return_value={ "Xq2d4D43YmBdUAOd3q6A0n1kaHUY766RE24xznk1Sgc=": { "shares": "27681494143232" } }) def test_monitor_indirect_sets_API_up_when_validator_indirect_monitoring_succesfull( self, _1, _2, _3, _4, _5, _6, _7) -> None: with mock.patch(DATA_SOURCE_INDIRECT_PATH, new_callable=PropertyMock) \ as mock_data_source_indirect: mock_data_source_indirect.return_value = self.dummy_full_node_1 self.validator_monitor.last_data_source_used = \ self.dummy_full_node_1 self.validator_monitor._archive_alerts_disabled = True self.validator_monitor.monitor_indirect() self.assertFalse(self.validator_monitor.data_wrapper.is_api_down) @patch(GET_STAKING_EVENTS_BY_HEIGHT_FUNCTION, return_value=None) @patch(GET_STAKING_ACCOUNT_FUNCTION, return_value={ "escrow": { "active": { "balance": "9999999999993" }, "debonding": { "balance": "9999999999993" } } }) @patch(GET_SIGNED_BLOCKS_FUNCTION, return_value={ "signatures": [ { "validator_address": "06140E5B1FE5D72BAA12AED7815A7E19BC7BDABA" }, { "validator_address": "7C87340EFE4BE695E80099AE3B0CAE545381925D" }, { "validator_address": "0D73013810841C092B8ACB1A9646F412B62EE14C" }, ] }) @patch(GET_BLOCK_HEADER_AT_HEIGHT_FUNCTION, return_value={"height": "55666"}) @patch(GET_CONSENSUS_BLOCK_FUNCTION, return_value={"height":"55666", \ "meta": "asndiasbdiabsidjbasjiaslnlasndlkandlkasldknasdlknaskbda"}) @patch(GET_SESSION_VALIDATORS_FUNCTION, return_value=[]) @patch(GET_STAKING_DELEGATIONS_INFO_FUNCTION, return_value={ "Xq2d4D43YmBdUAOd3q6A0n1kaHUY766RE24xznk1Sgc=": { "shares": "27681494143232" } }) def test_monitor_indirect_connects_data_source_with_api_if_monitoring_succesfull( self, _1, _2, _3, _4, _5, _6, _7) -> None: with mock.patch(DATA_SOURCE_INDIRECT_PATH, new_callable=PropertyMock) \ as mock_data_source_indirect: mock_data_source_indirect.return_value = self.dummy_full_node_1 self.validator_monitor.last_data_source_used = \ self.dummy_full_node_1 self.validator_monitor.last_data_source_used.disconnect_from_api( self.channel_set, self.logger) self.validator_monitor._archive_alerts_disabled = True self.validator_monitor.monitor_indirect() self.assertTrue(self.validator_monitor.last_data_source_used. is_connected_to_api_server) def test_monitor_indirect_full_node_sets_values_as_expected(self) -> None: self.full_node_monitor.monitor_indirect() self.assertEqual(self.full_node_monitor.node.bonded_balance, 0) self.assertFalse(self.full_node_monitor.node.is_active) @patch(GET_STAKING_DELEGATIONS_INFO_FUNCTION, return_value={ "Xq2d4D43YmBdUAOd3q6A0n1kaHUY766RE24xznk1Sgc=": { "shares": "27681494143232" } }) @patch(GET_STAKING_EVENTS_BY_HEIGHT_FUNCTION, return_value=None) @patch(GET_STAKING_ACCOUNT_FUNCTION, return_value={ "escrow": { "active": { "balance": "9999999999993" }, "debonding": { "balance": "9999999999993" } } }) @patch(GET_SIGNED_BLOCKS_FUNCTION, return_value={ "signatures": [ { "validator_address": "06140E5B1FE5D72BAA12AED7815A7E19BC7BDABA" }, { "validator_address": "7C87340EFE4BE695E80099AE3B0CAE545381925D" }, { "validator_address": "0D73013810841C092B8ACB1A9646F412B62EE14C" }, ] }) @patch(GET_BLOCK_HEADER_AT_HEIGHT_FUNCTION, return_value={"height": "55666"}) @patch(GET_CONSENSUS_BLOCK_FUNCTION, return_value={"height":"55666", \ "meta": "asndiasbdiabsidjbasjiaslnlasndlkandlkasldknasdlknaskbda"}) @patch(GET_SESSION_VALIDATORS_FUNCTION, return_value=[]) def test_monitor_indirect_validator_calls_monitor_archive_if_not_disabled( self, _1, _2, _3, _4, _5, _6, _7) -> None: with mock.patch(DATA_SOURCE_INDIRECT_PATH, new_callable=PropertyMock) \ as mock_data_source_indirect: mock_data_source_indirect.return_value = self.dummy_full_node_1 self.validator_monitor._monitor_archive_state = MagicMock() self.validator_monitor._monitor_indirect_validator() self.assertEqual( self.validator_monitor._monitor_archive_state.call_count, 1) @patch(GET_STAKING_EVENTS_BY_HEIGHT_FUNCTION, return_value=None) def test_monitor_archive_sets_catching_up_true_if_more_than_2_blocks_late( self, _1) -> None: with mock.patch(DATA_SOURCE_ARCHIVE_PATH, new_callable=PropertyMock) \ as mock_data_source_indirect: mock_data_source_indirect.return_value = self.dummy_full_node_1 # To make the monitor catch up archive_node_height = self.dummy_finalized_block_height + 4 self.dummy_full_node_1.update_finalized_block_height( archive_node_height, self.logger, self.channel_set) self.validator_monitor._last_height_checked = \ self.dummy_finalized_block_height self.validator_monitor._monitor_archive_state() self.assertTrue(self.validator_monitor._monitor_is_catching_up) @patch(GET_STAKING_EVENTS_BY_HEIGHT_FUNCTION, return_value=None) def test_monitor_archive_sets_catching_up_false_if_less_than_2_blocks_late( self, _1) -> None: with mock.patch(DATA_SOURCE_ARCHIVE_PATH, new_callable=PropertyMock) \ as mock_data_source_indirect: mock_data_source_indirect.return_value = self.dummy_full_node_1 self.dummy_full_node_1.update_finalized_block_height( self.dummy_finalized_block_height, self.logger, self.channel_set) self.validator_monitor._monitor_archive_state() self.assertFalse(self.validator_monitor._monitor_is_catching_up) @patch(GET_STAKING_EVENTS_BY_HEIGHT_FUNCTION, return_value=None) def test_monitor_archive_sets_catching_up_false_if_2_blocks_late( self, _1) -> None: with mock.patch(DATA_SOURCE_ARCHIVE_PATH, new_callable=PropertyMock) \ as mock_data_source_indirect: mock_data_source_indirect.return_value = self.dummy_full_node_1 self.dummy_full_node_1.update_finalized_block_height( self.dummy_finalized_block_height, self.logger, self.channel_set) self.validator_monitor._last_height_checked = \ self.dummy_finalized_block_height - 2 self.validator_monitor._monitor_archive_state() self.assertFalse(self.validator_monitor._monitor_is_catching_up) @patch(GET_STAKING_EVENTS_BY_HEIGHT_FUNCTION, return_value=None) def test_monitor_archive_raises_info_alert_if_monitoring_round_successful_and_error_alert_sent( self, _1) -> None: with mock.patch(DATA_SOURCE_ARCHIVE_PATH, new_callable=PropertyMock) \ as mock_data_source_indirect: mock_data_source_indirect.return_value = self.dummy_full_node_1 self.validator_monitor._no_live_archive_node_alert_sent = True self.validator_monitor._monitor_archive_state() self.assertEqual(self.counter_channel.info_count, 1) self.assertFalse( self.validator_monitor._no_live_archive_node_alert_sent) self.assertIsInstance(self.counter_channel.latest_alert, FoundLiveArchiveNodeAgainAlert) @patch(GET_STAKING_EVENTS_BY_HEIGHT_FUNCTION, return_value=None) def test_monitor_archive_no_alerts_if_monitoring_round_successful_error_alert_not_sent_previously( self, _1) -> None: with mock.patch(DATA_SOURCE_ARCHIVE_PATH, new_callable=PropertyMock) \ as mock_data_source_indirect: mock_data_source_indirect.return_value = self.dummy_full_node_1 self.validator_monitor._monitor_archive_state() self.assertTrue(self.counter_channel.no_alerts()) self.assertFalse( self.validator_monitor._no_live_archive_node_alert_sent) @patch(GET_STAKING_EVENTS_BY_HEIGHT_FUNCTION, return_value= \ [{"escrow" : {"take" : {"owner" : "entity_key_1", "tokens": "2000000000"}}}]) def test_monitor_archive_if_a_slashing_event_occurs_for_1_node(self, _1) -> None: with mock.patch(DATA_SOURCE_ARCHIVE_PATH, new_callable=PropertyMock) \ as mock_data_source_indirect: mock_data_source_indirect.return_value = self.dummy_full_node_1 self.data_sources = [self.dummy_validator_node_1] test_monitor = NodeMonitor(self.monitor_name, self.channel_set, self.logger, self.node_monitor_max_catch_up_blocks, self.redis, self.validator, self.archive_alerts_disabled, self.data_sources, TestInternalConf) # To make the monitor catch up archive_node_height = self.dummy_finalized_block_height + 4 self.dummy_full_node_1.update_finalized_block_height( archive_node_height, self.logger, self.channel_set) test_monitor._last_height_checked = \ self.dummy_finalized_block_height test_monitor._monitor_archive_state() self.assertEqual(self.counter_channel.critical_count, 1) @patch(GET_STAKING_EVENTS_BY_HEIGHT_FUNCTION, return_value= \ [{"escrow" : {"take" : {"owner" : "entity_key_1", "tokens": "2000000000"}}}, {"escrow" : {"take" : {"owner" : "entity_key_2", "tokens": "2000000000"}}}, {"escrow" : {"take" : {"owner" : "entity_key_3", "tokens": "2000000000"}}}]) def test_monitor_archive_if_a_slashing_event_occurs_for_3_nodes( self, _1) -> None: with mock.patch(DATA_SOURCE_ARCHIVE_PATH, new_callable=PropertyMock) \ as mock_data_source_indirect: mock_data_source_indirect.return_value = self.dummy_full_node_1 self.data_sources = [ self.dummy_validator_node_1, self.dummy_validator_node_2, self.dummy_validator_node_3 ] test_monitor = NodeMonitor(self.monitor_name, self.channel_set, self.logger, self.node_monitor_max_catch_up_blocks, self.redis, self.validator, self.archive_alerts_disabled, self.data_sources, TestInternalConf) # To make the monitor catch up archive_node_height = self.dummy_finalized_block_height + 4 self.dummy_full_node_1.update_finalized_block_height( archive_node_height, self.logger, self.channel_set) test_monitor._last_height_checked = \ self.dummy_finalized_block_height test_monitor._monitor_archive_state() self.assertEqual(self.counter_channel.critical_count, 3)
class TestBlockchainWithoutRedis(unittest.TestCase): def setUp(self) -> None: self.blockchain_name = 'testblockchain' self.logger = logging.getLogger('dummy') self.blockchain = Blockchain(name=self.blockchain_name, redis=None) self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel]) self.dummy_referendum_count, self.dummy_public_prop_count, \ self.dummy_council_prop_count = 10, 10, 10 self.dummy_validator_set_size = 120 self.dummy_referendum_info = {'end': '8568'} def test_str_returns_blockchain_name(self) -> None: self.assertEqual(self.blockchain_name, str(self.blockchain)) def test_referendum_count_None_by_default(self) -> None: self.assertIsNone(self.blockchain.referendum_count) def test_public_prop_count_None_by_default(self) -> None: self.assertIsNone(self.blockchain.public_prop_count) def test_council_prop_count_None_by_default(self) -> None: self.assertIsNone(self.blockchain.council_prop_count) def test_validator_set_size_None_by_default(self) -> None: self.assertIsNone(self.blockchain.validator_set_size) def test_status_returns_as_expected(self) -> None: self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) self.blockchain.set_council_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) self.assertEqual( self.blockchain.status(), "referendum_count={}, public_prop_count={}, " "council_prop_count={}, validator_set_size ={}".format( self.dummy_referendum_count, self.dummy_public_prop_count, self.dummy_council_prop_count, self.dummy_validator_set_size)) def test_set_referendum_count_raises_no_alerts_first_time_round( self) -> None: self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.referendum_count, self.dummy_referendum_count) def test_set_referendum_count_raises_no_alerts_if_same_referendum_count( self) -> None: self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.referendum_count, self.dummy_referendum_count) def test_set_referendum_count_raises_no_alerts_if_new_referendum_expired( self) -> None: self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) new_referendum_count = self.dummy_referendum_count + 1 self.blockchain.set_referendum_count(new_referendum_count, self.channel_set, self.logger, None) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.referendum_count, new_referendum_count) def test_set_referendum_count_info_alert_if_new_referendum_not_expired( self) -> None: self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) new_referendum_count = self.dummy_referendum_count + 1 self.blockchain.set_referendum_count(new_referendum_count, self.channel_set, self.logger, self.dummy_referendum_info) self.assertEqual(self.counter_channel.info_count, 1) self.assertIsInstance(self.counter_channel.latest_alert, NewReferendumAlert) self.assertEqual(self.blockchain.referendum_count, new_referendum_count) def test_set_public_prop_count_raises_no_alerts_first_time_round( self) -> None: self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.public_prop_count, self.dummy_public_prop_count) def test_set_public_prop_count_raises_no_alerts_if_same_count( self) -> None: self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.public_prop_count, self.dummy_public_prop_count) def test_set_public_prop_count_1_info_alert_if_increase_by_1(self) -> None: self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) new_public_prop_count = self.dummy_public_prop_count + 1 self.blockchain.set_public_prop_count(new_public_prop_count, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertIsInstance(self.counter_channel.latest_alert, NewPublicProposalAlert) self.assertEqual(self.blockchain.public_prop_count, new_public_prop_count) def test_set_public_prop_count_2_info_alerts_if_increase_by_2( self) -> None: self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) new_public_prop_count = self.dummy_public_prop_count + 2 self.blockchain.set_public_prop_count(new_public_prop_count, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 2) self.assertIsInstance(self.counter_channel.latest_alert, NewPublicProposalAlert) self.assertEqual(self.blockchain.public_prop_count, new_public_prop_count) def test_set_council_prop_count_raises_no_alerts_first_time_round( self) -> None: self.blockchain.set_council_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.council_prop_count, self.dummy_council_prop_count) def test_set_council_prop_count_raises_no_alerts_if_same_count( self) -> None: self.blockchain.set_council_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) self.blockchain.set_public_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.council_prop_count, self.dummy_council_prop_count) def test_set_council_prop_count_info_alert_if_increase_by_1(self) -> None: self.blockchain.set_council_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) new_council_prop_count = self.dummy_council_prop_count + 1 self.blockchain.set_council_prop_count(new_council_prop_count, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertIsInstance(self.counter_channel.latest_alert, NewCouncilProposalAlert) self.assertEqual(self.blockchain.council_prop_count, new_council_prop_count) def test_set_council_prop_count_info_alert_if_increase_by_2(self) -> None: self.blockchain.set_council_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) new_council_prop_count = self.dummy_council_prop_count + 2 self.blockchain.set_council_prop_count(new_council_prop_count, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 2) self.assertIsInstance(self.counter_channel.latest_alert, NewCouncilProposalAlert) self.assertEqual(self.blockchain.council_prop_count, new_council_prop_count) def test_set_validator_set_size_no_alerts_first_time_round(self) -> None: self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.validator_set_size, self.dummy_validator_set_size) def test_set_validator_set_size_no_alerts_if_same_size(self) -> None: self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.validator_set_size, self.dummy_validator_set_size) def test_set_validator_set_size_info_alert_if_size_decreased(self) -> None: self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) new_validator_set_size = self.dummy_validator_set_size - 2 self.blockchain.set_validator_set_size(new_validator_set_size, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertIsInstance(self.counter_channel.latest_alert, ValidatorSetSizeDecreasedAlert) self.assertEqual(self.blockchain.validator_set_size, new_validator_set_size) def test_set_validator_set_size_info_alert_if_size_increased(self) -> None: self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) new_validator_set_size = self.dummy_validator_set_size + 2 self.blockchain.set_validator_set_size(new_validator_set_size, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertIsInstance(self.counter_channel.latest_alert, ValidatorSetSizeIncreasedAlert) self.assertEqual(self.blockchain.validator_set_size, new_validator_set_size)
class TestBlockchainWithoutRedis(unittest.TestCase): def setUp(self) -> None: self.blockchain_name = 'testblockchain' self.logger = logging.getLogger('dummy') self.blockchain = Blockchain(name=self.blockchain_name, redis=None) self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.dummy_referendum_count, self.dummy_public_prop_count, \ self.dummy_council_prop_count = 10, 10, 10 self.dummy_validator_set_size = 120 self.dummy_referendum_info_ongoing = { 'Ongoing': { 'proposalHash': '0x345jtg8ergfg8df89h9we9t9sd9g9gsd9g9sdfg', 'end': 124143848, 'threshold': 'Supermajorityapproval', 'delay': 11549, 'tally': { 'ayes': '4544545 KSM', 'nayes': '3454 KSM', 'turnout': '4545454454 KSM' } } } self.dummy_referendum_info_finished = { 'Finished': { 'approved': False, 'end': 124143848 } } def test_str_returns_blockchain_name(self) -> None: self.assertEqual(self.blockchain_name, str(self.blockchain)) def test_referendum_count_None_by_default(self) -> None: self.assertIsNone(self.blockchain.referendum_count) def test_public_prop_count_None_by_default(self) -> None: self.assertIsNone(self.blockchain.public_prop_count) def test_council_prop_count_None_by_default(self) -> None: self.assertIsNone(self.blockchain.council_prop_count) def test_validator_set_size_None_by_default(self) -> None: self.assertIsNone(self.blockchain.validator_set_size) def test_status_returns_as_expected(self) -> None: self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) self.blockchain.set_council_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) self.assertEqual( self.blockchain.status(), "referendum_count={}, public_prop_count={}, " "council_prop_count={}, validator_set_size ={}".format( self.dummy_referendum_count, self.dummy_public_prop_count, self.dummy_council_prop_count, self.dummy_validator_set_size)) def test_set_referendum_count_raises_no_alerts_first_time_round( self) -> None: self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.referendum_count, self.dummy_referendum_count) def test_set_referendum_count_raises_no_alerts_if_same_referendum_count( self) -> None: self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.referendum_count, self.dummy_referendum_count) def test_set_referendum_count_raises_no_alerts_if_referendum_data_cleared( self) -> None: self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) new_referendum_count = self.dummy_referendum_count + 1 self.blockchain.set_referendum_count(new_referendum_count, self.channel_set, self.logger, None) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.referendum_count, new_referendum_count) def test_set_referendum_count_raises_no_alerts_if_referendum_finished_not_cleared( self) -> None: self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) new_referendum_count = self.dummy_referendum_count + 1 self.blockchain.set_referendum_count( new_referendum_count, self.channel_set, self.logger, self.dummy_referendum_info_finished) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.referendum_count, new_referendum_count) def test_set_referendum_count_info_alert_if_new_referendum_ongoing( self) -> None: self.blockchain.set_referendum_count(self.dummy_referendum_count, self.channel_set, self.logger) new_referendum_count = self.dummy_referendum_count + 1 self.blockchain.set_referendum_count( new_referendum_count, self.channel_set, self.logger, self.dummy_referendum_info_ongoing) self.assertEqual(self.counter_channel.info_count, 1) self.assertIsInstance(self.counter_channel.latest_alert, NewReferendumAlert) self.assertEqual(self.blockchain.referendum_count, new_referendum_count) def test_set_public_prop_count_raises_no_alerts_first_time_round( self) -> None: self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.public_prop_count, self.dummy_public_prop_count) def test_set_public_prop_count_raises_no_alerts_if_same_count( self) -> None: self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.public_prop_count, self.dummy_public_prop_count) def test_set_public_prop_count_1_info_alert_if_increase_by_1(self) -> None: self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) new_public_prop_count = self.dummy_public_prop_count + 1 self.blockchain.set_public_prop_count(new_public_prop_count, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertIsInstance(self.counter_channel.latest_alert, NewPublicProposalAlert) self.assertEqual(self.blockchain.public_prop_count, new_public_prop_count) def test_set_public_prop_count_2_info_alerts_if_increase_by_2( self) -> None: self.blockchain.set_public_prop_count(self.dummy_public_prop_count, self.channel_set, self.logger) new_public_prop_count = self.dummy_public_prop_count + 2 self.blockchain.set_public_prop_count(new_public_prop_count, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 2) self.assertIsInstance(self.counter_channel.latest_alert, NewPublicProposalAlert) self.assertEqual(self.blockchain.public_prop_count, new_public_prop_count) def test_set_council_prop_count_raises_no_alerts_first_time_round( self) -> None: self.blockchain.set_council_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.council_prop_count, self.dummy_council_prop_count) def test_set_council_prop_count_raises_no_alerts_if_same_count( self) -> None: self.blockchain.set_council_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) self.blockchain.set_public_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.council_prop_count, self.dummy_council_prop_count) def test_set_council_prop_count_info_alert_if_increase_by_1(self) -> None: self.blockchain.set_council_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) new_council_prop_count = self.dummy_council_prop_count + 1 self.blockchain.set_council_prop_count(new_council_prop_count, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertIsInstance(self.counter_channel.latest_alert, NewCouncilProposalAlert) self.assertEqual(self.blockchain.council_prop_count, new_council_prop_count) def test_set_council_prop_count_info_alert_if_increase_by_2(self) -> None: self.blockchain.set_council_prop_count(self.dummy_council_prop_count, self.channel_set, self.logger) new_council_prop_count = self.dummy_council_prop_count + 2 self.blockchain.set_council_prop_count(new_council_prop_count, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 2) self.assertIsInstance(self.counter_channel.latest_alert, NewCouncilProposalAlert) self.assertEqual(self.blockchain.council_prop_count, new_council_prop_count) def test_set_validator_set_size_no_alerts_first_time_round(self) -> None: self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.validator_set_size, self.dummy_validator_set_size) def test_set_validator_set_size_no_alerts_if_same_size(self) -> None: self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertEqual(self.blockchain.validator_set_size, self.dummy_validator_set_size) def test_set_validator_set_size_info_alert_if_size_decreased(self) -> None: self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) new_validator_set_size = self.dummy_validator_set_size - 2 self.blockchain.set_validator_set_size(new_validator_set_size, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertIsInstance(self.counter_channel.latest_alert, ValidatorSetSizeDecreasedAlert) self.assertEqual(self.blockchain.validator_set_size, new_validator_set_size) def test_set_validator_set_size_info_alert_if_size_increased(self) -> None: self.blockchain.set_validator_set_size(self.dummy_validator_set_size, self.channel_set, self.logger) new_validator_set_size = self.dummy_validator_set_size + 2 self.blockchain.set_validator_set_size(new_validator_set_size, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertIsInstance(self.counter_channel.latest_alert, ValidatorSetSizeIncreasedAlert) self.assertEqual(self.blockchain.validator_set_size, new_validator_set_size)
def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.monitor_name = 'testnodemonitor' self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.node_monitor_max_catch_up_blocks = \ TestInternalConf.node_monitor_max_catch_up_blocks self.redis = None self.archive_alerts_disabled = False self.data_sources = [] self.chain = 'testchain' self.full_node_name = 'testfullnode' self.full_node_api_url = '123.123.123.11:9944' self.full_node_consensus_key = "ANDSAdisadjasdaANDAsa" self.full_node_tendermint_key = "ASFLNAFIISDANNSDAKKS2313AA" self.full_node_entity_public_key = "a98dabsfkjabfkjabsf9j" self.full_node_staking_address = "asdsasdsdsaasdsdaswwad" self.full_node = Node( self.full_node_name, self.full_node_api_url, None, NodeType.NON_VALIDATOR_FULL_NODE, '', self.chain, None, True, self.full_node_consensus_key, self.full_node_tendermint_key, self.full_node_staking_address, self.full_node_entity_public_key, TestInternalConf) self.full_node_monitor = NodeMonitor( self.monitor_name, self.channel_set, self.logger, self.node_monitor_max_catch_up_blocks, self.redis, self.full_node, self.archive_alerts_disabled, self.data_sources, TestInternalConf) self.validator_name = 'testvalidator' self.validator_api_url = '13.13.14.11:9944' self.validator_consensus_key = "KASDB01923udlakd19sad" self.validator_tendermint_key = "ALSFNF9)901jjelakNALKNDLKA" self.validator_node_public_key = "DFJGDF8G898fdghb98dg9wetg9we00w" self.validator_node_entity_public_key = "s12adsdghas9as0sa9dhnaskdlan" self.validator_node_staking_address = "jujuujsmjmsjmaklzsdjsdnanz" self.validator = Node( self.validator_name, self.validator_api_url, None, NodeType.VALIDATOR_FULL_NODE, self.validator_node_public_key, self.chain, None, True, self.validator_consensus_key, self.validator_tendermint_key, self.validator_node_staking_address, self.validator_node_entity_public_key, TestInternalConf) self.validator_monitor = NodeMonitor( self.monitor_name, self.channel_set, self.logger, self.node_monitor_max_catch_up_blocks, self.redis, self.validator, self.archive_alerts_disabled, self.data_sources, TestInternalConf) self.dummy_last_height_checked = 1000 self.dummy_bonded_balance = scale_to_giga(5) self.dummy_debonding_balance = scale_to_giga(5) self.dummy_shares_balance = scale_to_giga(5) self.dummy_height_to_check = 1000 self.dummy_no_of_peers = 100 self.dummy_is_missing_blocks = False self.dummy_active = True self.dummy_finalized_block_height = 34535 self.dummy_api_url_1 = "11.22.33.11:9944" self.dummy_api_url_2 = "11.22.33.12:9944" self.dummy_api_url_3 = "11.22.33.13:9944" self.dummy_api_url_4 = "11.22.33.14:9944" self.dummy_api_url_5 = "11.22.33.15:9944" self.dummy_node_name_1 = "testnode1" self.dummy_node_name_2 = "testnode2" self.dummy_node_name_3 = "testnode3" self.dummy_node_name_4 = "testnode4" self.dummy_node_name_5 = "testnode5" self.dummy_validator_node_name_2 = "testvalidatornode2" self.dummy_validator_node_name_3 = "testvalidatornode3" self.dummy_node_consensus_key_1 = "consensus_key_1" self.dummy_node_consensus_key_2 = "consensus_key_2" self.dummy_node_consensus_key_3 = "consensus_key_3" self.dummy_node_tendermint_key_1 = "consensus_key_1" self.dummy_node_tendermint_key_2 = "consensus_key_2" self.dummy_node_tendermint_key_3 = "consensus_key_3" self.dummy_node_entity_public_key_1 = "entity_key_1" self.dummy_node_entity_public_key_2 = "entity_key_2" self.dummy_node_entity_public_key_3 = "entity_key_3" self.dummy_node_staking_address_1 = "staking-key_1" self.dummy_node_staking_address_2 = "staking_key_2" self.dummy_node_staking_address_3 = "staking_key_3" self.dummy_full_node_1 = Node( name=self.dummy_node_name_1, api_url=self.dummy_api_url_1, prometheus_endpoint=None, node_type=NodeType.NON_VALIDATOR_FULL_NODE, node_public_key='', chain=self.chain, redis=None, is_archive_node=True, consensus_public_key='', tendermint_address_key='', staking_address='', entity_public_key='', internal_conf=TestInternalConf) self.dummy_full_node_2 = Node( name=self.dummy_node_name_2, api_url=self.dummy_api_url_2, prometheus_endpoint=None, node_type=NodeType.NON_VALIDATOR_FULL_NODE, node_public_key='', chain=self.chain, redis=None, is_archive_node=True, consensus_public_key='', tendermint_address_key='', staking_address='', entity_public_key='', internal_conf=TestInternalConf) self.dummy_full_node_3 = Node( name=self.dummy_node_name_3, api_url=self.dummy_api_url_3, prometheus_endpoint=None, node_type=NodeType.NON_VALIDATOR_FULL_NODE, node_public_key='', chain=self.chain, redis=None, is_archive_node=True, consensus_public_key='', tendermint_address_key='', staking_address='', entity_public_key='', internal_conf=TestInternalConf) self.dummy_full_node_4 = Node( name=self.dummy_node_name_5, api_url=self.dummy_api_url_5, prometheus_endpoint=None, node_type=NodeType.NON_VALIDATOR_FULL_NODE, node_public_key='', chain=self.chain, redis=None, is_archive_node=False, consensus_public_key='', tendermint_address_key='', staking_address='', entity_public_key='', internal_conf=TestInternalConf) self.dummy_take_event_owner = { "escrow": { "take": { "owner": self.dummy_node_entity_public_key_1, "tokens": "2000000000" } } } self.dummy_validator_node_1 = Node( name=self.dummy_node_name_4, api_url=self.dummy_api_url_4, prometheus_endpoint=None, node_type=NodeType.VALIDATOR_FULL_NODE, node_public_key=self.validator_node_public_key, chain=self.chain, redis=None, is_archive_node=True, consensus_public_key=self.dummy_node_consensus_key_1, tendermint_address_key=self.dummy_node_tendermint_key_1, staking_address=self.dummy_node_staking_address_1, entity_public_key=self.dummy_node_entity_public_key_1, internal_conf=TestInternalConf) self.dummy_validator_node_2 = Node( name=self.dummy_validator_node_name_2, api_url=self.dummy_api_url_4, prometheus_endpoint=None, node_type=NodeType.VALIDATOR_FULL_NODE, node_public_key=self.validator_node_public_key, chain=self.chain, redis=None, is_archive_node=True, consensus_public_key=self.dummy_node_consensus_key_2, tendermint_address_key=self.dummy_node_tendermint_key_2, staking_address=self.dummy_node_staking_address_2, entity_public_key=self.dummy_node_entity_public_key_2, internal_conf=TestInternalConf) self.dummy_validator_node_3 = Node( name=self.dummy_validator_node_name_3, api_url=self.dummy_api_url_4, prometheus_endpoint=None, node_type=NodeType.VALIDATOR_FULL_NODE, node_public_key=self.validator_node_public_key, chain=self.chain, redis=None, is_archive_node=True, consensus_public_key=self.dummy_node_consensus_key_3, tendermint_address_key=self.dummy_node_tendermint_key_3, staking_address=self.dummy_node_staking_address_3, entity_public_key=self.dummy_node_entity_public_key_3, internal_conf=TestInternalConf)
class TestNodeWithoutRedis(unittest.TestCase): def setUp(self) -> None: self.node_name = 'testnode' self.logger = logging.getLogger('dummy') self.downtime_initial_alert_delay = \ TestInternalConf.downtime_initial_alert_delay self.downtime_initial_alert_delay_with_error_margin = \ self.downtime_initial_alert_delay + timedelta(seconds=0.5) self.downtime_reminder_alert_interval = \ TestInternalConf.downtime_reminder_interval_seconds self.downtime_reminder_alert_interval_with_error_margin = \ self.downtime_reminder_alert_interval + timedelta(seconds=0.5) self.max_missed_blocks_time_interval = \ TestInternalConf.max_missed_blocks_time_interval self.max_missed_blocks_time_interval_with_error_margin = \ self.max_missed_blocks_time_interval + timedelta(seconds=0.5) self.max_missed_blocks_in_time_interval = \ TestInternalConf.max_missed_blocks_in_time_interval self.full_node = Node(name=self.node_name, rpc_url=None, node_type=NodeType.NON_VALIDATOR_FULL_NODE, pubkey=None, network='', redis=None, internal_conf=TestInternalConf) self.validator = Node(name=self.node_name, rpc_url=None, node_type=NodeType.VALIDATOR_FULL_NODE, pubkey=None, network='', redis=None, internal_conf=TestInternalConf) self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel]) self.dummy_exception = DummyException() self.dummy_block_height = -1 self.dummy_block_time = datetime.min + timedelta(days=123) self.dummy_block_time_after_time_interval = \ self.dummy_block_time + \ self.max_missed_blocks_time_interval_with_error_margin self.dummy_missing_validators = -1 self.dummy_voting_power = 1000 self.dummy_no_of_peers = 1000 self.peers_validator_danger_boundary = \ TestInternalConf.validator_peer_danger_boundary self.peers_less_than_validator_danger_boundary = \ self.peers_validator_danger_boundary - 2 self.peers_more_than_validator_danger_boundary = \ self.peers_validator_danger_boundary + 2 self.peers_validator_safe_boundary = \ TestInternalConf.validator_peer_safe_boundary self.peers_less_than_validator_safe_boundary = \ self.peers_validator_safe_boundary - 2 self.peers_more_than_validator_safe_boundary = \ self.peers_validator_safe_boundary + 2 self.peers_full_node_danger_boundary = \ TestInternalConf.full_node_peer_danger_boundary self.peers_less_than_full_node_danger_boundary = \ self.peers_full_node_danger_boundary - 2 self.peers_more_than_full_node_danger_boundary = \ self.peers_full_node_danger_boundary + 2 def test_is_validator_true_if_is_validator(self): self.assertTrue(self.validator.is_validator) def test_is_validator_false_if_not_validator(self): self.assertFalse(self.full_node.is_validator) def test_is_down_false_by_default(self): self.assertFalse(self.validator.is_down) def test_is_missing_blocks_false_by_default(self): self.assertFalse(self.validator.is_missing_blocks) def test_consecutive_blocks_missed_is_0_by_default(self): self.assertEqual(self.validator.consecutive_blocks_missed_so_far, 0) def test_voting_power_is_none_by_default(self): self.assertIsNone(self.validator.voting_power) def test_catching_up_is_false_by_default(self): self.assertFalse(self.validator.catching_up) def test_no_of_peers_is_none_by_default(self): self.assertIsNone(self.validator.no_of_peers) def test_status_returns_three_values(self): self.validator._voting_power = 123 self.validator._catching_up = True self.validator._no_of_peers = 999 self.assertEqual( self.validator.status(), 'voting_power=123, ' 'catching_up=True, ' 'number_of_peers=999') def test_set_as_down_validator(self): NODE = self.validator self.assertFalse(NODE.is_down) # First one sets validator to down but sends no alerts NODE.set_as_down(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertTrue(NODE.is_down) self.counter_channel.reset() # Second one sends info alert and keeps validator down NODE.set_as_down(self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertTrue(NODE.is_down) self.counter_channel.reset() # Next is the initial downtime alert, but this is # not sent if not enough time has passed for it NODE.set_as_down(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertTrue(NODE.is_down) self.counter_channel.reset() # ...if enough time passed for an initial alert, a major alert is sent sleep(self.downtime_initial_alert_delay_with_error_margin.seconds) NODE.set_as_down(self.channel_set, self.logger) self.assertEqual(self.counter_channel.major_count, 1) self.assertTrue(NODE.is_down) self.counter_channel.reset() # Next is the downtime reminder alert, but this is # not sent if not enough time has passed for it NODE.set_as_down(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertTrue(NODE.is_down) self.counter_channel.reset() # ...if enough time passed for a reminder, a major alert is sent again sleep(self.downtime_reminder_alert_interval_with_error_margin.seconds) NODE.set_as_down(self.channel_set, self.logger) self.assertEqual(self.counter_channel.major_count, 1) self.assertTrue(NODE.is_down) self.counter_channel.reset() def test_set_as_down_full_node(self): NODE = self.full_node self.assertFalse(NODE.is_down) # First one sets full node to down but sends no alerts NODE.set_as_down(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertTrue(NODE.is_down) self.counter_channel.reset() # Second one sends info alert and keeps full node down NODE.set_as_down(self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertTrue(NODE.is_down) self.counter_channel.reset() # Next is the initial downtime alert, but this is # not sent if not enough time has passed for it NODE.set_as_down(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertTrue(NODE.is_down) self.counter_channel.reset() # ...if enough time passed for an initial alert, a minor alert is sent sleep(self.downtime_initial_alert_delay_with_error_margin.seconds) NODE.set_as_down(self.channel_set, self.logger) self.assertEqual(self.counter_channel.minor_count, 1) self.assertTrue(NODE.is_down) self.counter_channel.reset() # Next is the downtime reminder alert, but this is # not sent if not enough time has passed for it NODE.set_as_down(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertTrue(NODE.is_down) self.counter_channel.reset() # ...if enough time passed for a reminder, a minor alert is sent again sleep(self.downtime_reminder_alert_interval_with_error_margin.seconds) NODE.set_as_down(self.channel_set, self.logger) self.assertEqual(self.counter_channel.minor_count, 1) self.assertTrue(NODE.is_down) self.counter_channel.reset() def test_set_as_up_sends_no_alerts_if_not_down(self): self.validator.set_as_up(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertFalse(self.validator.is_down) def test_set_as_up_sends_no_alerts_if_initial_downtime_alert_not_sent( self): self.validator._went_down_at = datetime.min # non-None, i.e. down self.validator._initial_downtime_alert_sent = False # Confirm that nodes down self.assertTrue(self.validator.is_down) self.counter_channel.reset() # ignore previous alerts self.validator.set_as_up(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertFalse(self.validator.is_down) def test_set_as_up_sends_info_alerts_if_initial_downtime_alert_sent(self): self.validator._went_down_at = datetime.min # non-None, i.e. down self.validator._initial_downtime_alert_sent = True # Confirm that nodes down self.assertTrue(self.validator.is_down) self.counter_channel.reset() # ignore previous alerts self.validator.set_as_up(self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) self.assertFalse(self.validator.is_down) def test_set_as_up_resets_initial_downtime_alert_timing(self): self.validator.set_as_down(self.channel_set, self.logger) self.validator.set_as_down(self.channel_set, self.logger) sleep(self.downtime_initial_alert_delay_with_error_margin.seconds) self.validator.set_as_up(self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_as_down(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertTrue(self.validator.is_down) # Without the set_as_up, the set_as_down produces an alert. We can try # this out by first setting the validator back to up self.validator.set_as_up(self.channel_set, self.logger) self.validator.set_as_down(self.channel_set, self.logger) self.validator.set_as_down(self.channel_set, self.logger) sleep(self.downtime_initial_alert_delay_with_error_margin.seconds) # self.validator.set_as_up(self.channel_set, self.logger) # !! self.counter_channel.reset() # ignore previous alerts self.validator.set_as_down(self.channel_set, self.logger) self.assertEqual(self.counter_channel.major_count, 1) self.assertTrue(self.validator.is_down) def test_set_as_up_resets_downtime_reminder_alert_timing(self): self.validator.set_as_down(self.channel_set, self.logger) self.validator.set_as_down(self.channel_set, self.logger) sleep(self.downtime_initial_alert_delay_with_error_margin.seconds) self.validator.set_as_down(self.channel_set, self.logger) sleep(self.downtime_reminder_alert_interval_with_error_margin.seconds) self.validator.set_as_up(self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_as_down(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) self.assertTrue(self.validator.is_down) # Without the set_as_up, the set_as_down produces an alert. We can try # this out by first setting the validator back to up self.validator.set_as_up(self.channel_set, self.logger) self.validator.set_as_down(self.channel_set, self.logger) self.validator.set_as_down(self.channel_set, self.logger) sleep(self.downtime_initial_alert_delay_with_error_margin.seconds) self.validator.set_as_down(self.channel_set, self.logger) sleep(self.downtime_reminder_alert_interval_with_error_margin.seconds) # self.validator.set_as_up(self.channel_set, self.logger) # !! self.counter_channel.reset() # ignore previous alerts self.validator.set_as_down(self.channel_set, self.logger) self.assertEqual(self.counter_channel.major_count, 1) self.assertTrue(self.validator.is_down) def test_first_missed_block_increases_missed_blocks_count_but_no_alerts( self): if TestInternalConf.missed_blocks_danger_boundary != 5: self.fail('Expected missed blocks danger boundary to be 5.') self.validator.add_missed_block(self.dummy_block_height, self.dummy_block_time, self.dummy_missing_validators, self.channel_set, self.logger) self.assertEqual(self.validator.consecutive_blocks_missed_so_far, 1) self.assertTrue(self.counter_channel.no_alerts()) def test_four_missed_blocks_increases_missed_blocks_count_and_alerts(self): if TestInternalConf.missed_blocks_danger_boundary != 5: self.fail('Expected missed blocks danger boundary to be 5.') for i in range(4): self.validator.add_missed_block(self.dummy_block_height, self.dummy_block_time, self.dummy_missing_validators, self.channel_set, self.logger) self.assertEqual(self.validator.consecutive_blocks_missed_so_far, 4) self.assertEqual(self.counter_channel.info_count, 3) # 1 raises no alerts, 2,3,4 raise an info alert def test_five_missed_blocks_increases_missed_blocks_count_and_alerts(self): if TestInternalConf.missed_blocks_danger_boundary != 5: self.fail('Expected missed blocks danger boundary to be 5.') for i in range(5): self.validator.add_missed_block(self.dummy_block_height, self.dummy_block_time, self.dummy_missing_validators, self.channel_set, self.logger) self.assertEqual(self.validator.consecutive_blocks_missed_so_far, 5) self.assertEqual(self.counter_channel.info_count, 3) self.assertEqual(self.counter_channel.minor_count, 1) # 1 raises no alerts, 2,3,4 raise an info alert, 5 raises a minor alert def test_ten_missed_blocks_increases_missed_blocks_count_and_alerts(self): if TestInternalConf.missed_blocks_danger_boundary != 5: self.fail('Expected missed blocks danger boundary to be 5.') for i in range(10): self.validator.add_missed_block(self.dummy_block_height, self.dummy_block_time, self.dummy_missing_validators, self.channel_set, self.logger) self.assertEqual(self.validator.consecutive_blocks_missed_so_far, 10) self.assertEqual(self.counter_channel.info_count, 3) self.assertEqual(self.counter_channel.minor_count, 1) self.assertEqual(self.counter_channel.major_count, 1) # 1 raises no alerts, 2,3,4 raise an info alert, # 5 raises a minor alert, 10 raises a major alert def test_ten_non_consecutive_missed_blocks_within_time_interval_triggers_major_alert( self): if TestInternalConf.missed_blocks_danger_boundary != 5: self.fail('Expected missed blocks danger boundary to be 5.') # Miss 9 non-consecutive blocks for i in range(9): self.validator.add_missed_block(self.dummy_block_height, self.dummy_block_time, self.dummy_missing_validators, self.channel_set, self.logger) self.validator.clear_missed_blocks(self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts # Miss 10th block within time interval self.validator.add_missed_block(self.dummy_block_height, self.dummy_block_time, self.dummy_missing_validators, self.channel_set, self.logger) self.assertEqual(self.validator.consecutive_blocks_missed_so_far, 1) self.assertEqual(self.counter_channel.major_count, 1) def test_ten_non_consecutive_missed_blocks_outside_time_interval_does_nothing( self): if TestInternalConf.missed_blocks_danger_boundary != 5: self.fail('Expected missed blocks danger boundary to be 5.') # Miss 9 non-consecutive blocks for i in range(9): self.validator.add_missed_block(self.dummy_block_height, self.dummy_block_time, self.dummy_missing_validators, self.channel_set, self.logger) self.validator.clear_missed_blocks(self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts # Miss 10th block outside of time interval self.validator.add_missed_block( self.dummy_block_height, self.dummy_block_time_after_time_interval, self.dummy_missing_validators, self.channel_set, self.logger) self.assertEqual(self.validator.consecutive_blocks_missed_so_far, 1) self.assertTrue(self.counter_channel.no_alerts()) def test_clear_missed_blocks_raises_no_alert_if_was_not_missing_blocks( self): self.validator.clear_missed_blocks(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_clear_missed_blocks_raises_info_alert_if_no_longer_missing_blocks_for_one_missed_block( self): # Miss one block self.validator.add_missed_block(self.dummy_block_height, self.dummy_block_time, self.dummy_missing_validators, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.clear_missed_blocks(self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_clear_missed_blocks_raises_info_alert_if_no_longer_missing_blocks_for_two_missed_blocks( self): # Miss two blocks self.validator.add_missed_block(self.dummy_block_height, self.dummy_block_time, self.dummy_missing_validators, self.channel_set, self.logger) self.validator.add_missed_block(self.dummy_block_height, self.dummy_block_time, self.dummy_missing_validators, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.clear_missed_blocks(self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) def test_set_voting_power_raises_no_alerts_first_time_round(self): self.validator.set_voting_power(0, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_set_voting_power_raises_no_alerts_if_voting_power_the_same(self): self.validator.set_voting_power(self.dummy_voting_power, self.channel_set, self.logger) self.validator.set_voting_power(self.dummy_voting_power, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_set_voting_power_raises_info_alert_if_voting_power_increases_from_non_0( self): increased_voting_power = self.dummy_voting_power + 1 self.validator.set_voting_power(self.dummy_voting_power, self.channel_set, self.logger) self.validator.set_voting_power(increased_voting_power, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) def test_set_voting_power_raises_info_alert_if_voting_power_increases_from_0( self): # This is just to cover the unique message when power increases from 0 self.validator.set_voting_power(0, self.channel_set, self.logger) self.validator.set_voting_power(self.dummy_voting_power, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) def test_set_voting_power_raises_info_alert_if_voting_power_decreases_to_non_0( self): decreased_voting_power = self.dummy_voting_power - 1 self.validator.set_voting_power(self.dummy_voting_power, self.channel_set, self.logger) self.validator.set_voting_power(decreased_voting_power, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) def test_set_voting_power_raises_major_alert_if_voting_power_decreases_to_0( self): self.validator.set_voting_power(self.dummy_voting_power, self.channel_set, self.logger) self.validator.set_voting_power(0, self.channel_set, self.logger) self.assertEqual(self.counter_channel.major_count, 1) def test_set_catching_up_raises_minor_alert_first_time_round_if_true(self): self.validator.set_catching_up(True, self.channel_set, self.logger) self.assertEqual(self.counter_channel.minor_count, 1) def test_set_catching_up_raises_no_alerts_first_time_round_if_false(self): self.validator.set_catching_up(False, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_set_catching_up_raises_no_alerts_if_from_true_to_true(self): self.validator.set_catching_up(True, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_catching_up(True, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_set_catching_up_raises_no_alerts_if_from_false_to_false(self): self.validator.set_catching_up(False, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_catching_up(False, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_set_catching_up_raises_minor_alert_if_from_false_to_true(self): self.validator.set_catching_up(False, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_catching_up(True, self.channel_set, self.logger) self.assertEqual(self.counter_channel.minor_count, 1) def test_set_catching_up_raises_info_alert_if_from_true_to_false(self): self.validator.set_catching_up(True, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_catching_up(False, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) def test_set_no_of_peers_raises_no_alerts_first_time_round_for_validator( self): self.validator.set_no_of_peers(self.dummy_no_of_peers, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_set_no_of_peers_raises_no_alerts_first_time_round_for_full_node( self): self.full_node.set_no_of_peers(self.dummy_no_of_peers, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_set_no_of_peers_raises_no_alerts_if_increase_for_validator_if_outside_safe_range( self): increased_no_of_peers = self.dummy_no_of_peers + 1 self.validator.set_no_of_peers(self.dummy_no_of_peers, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_no_of_peers(increased_no_of_peers, self.channel_set, self.logger) self.assertEqual(self.counter_channel.minor_count, 0) self.assertEqual(self.counter_channel.major_count, 0) self.assertEqual(self.counter_channel.info_count, 0) self.assertEqual(self.counter_channel.error_count, 0) def test_set_no_of_peers_raises_info_alert_if_increase_for_full_node_if_inside_danger( self): self.full_node.set_no_of_peers( self.peers_less_than_full_node_danger_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.full_node.set_no_of_peers( self.peers_less_than_full_node_danger_boundary + 1, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) def test_set_no_of_peers_raises_no_alerts_if_increase_for_full_node_if_outside_danger( self): self.full_node.set_no_of_peers( self.peers_more_than_full_node_danger_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.full_node.set_no_of_peers( self.peers_more_than_full_node_danger_boundary + 1, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_set_no_of_peers_raises_info_alert_if_increase_for_full_node_if_inside_to_outside_danger( self): self.full_node.set_no_of_peers( self.peers_less_than_full_node_danger_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.full_node.set_no_of_peers( self.peers_more_than_full_node_danger_boundary, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) def test_set_no_of_peers_raises_info_alert_if_increase_for_validator_if_inside_danger( self): self.validator.set_no_of_peers( self.peers_less_than_validator_danger_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_no_of_peers( self.peers_less_than_validator_danger_boundary + 1, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) def test_set_no_of_peers_raises_info_alert_if_increase_for_validator_if_outside_danger_inside_safe( self): self.validator.set_no_of_peers(self.peers_validator_danger_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_no_of_peers( self.peers_validator_danger_boundary + 1, self.channel_set, self.logger) self.assertEqual(self.counter_channel.info_count, 1) def test_set_no_of_peers_raises_info_alert_if_decrease_for_validator_if_outside_danger_inside_safe( self): self.validator.set_no_of_peers(self.peers_validator_safe_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_no_of_peers(self.peers_validator_safe_boundary - 1, self.channel_set, self.logger) self.assertEqual(self.counter_channel.minor_count, 1) def test_set_no_of_peers_raises_minor_alert_if_decrease_for_full_node_if_inside_danger( self): self.full_node.set_no_of_peers( self.peers_more_than_full_node_danger_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.full_node.set_no_of_peers( self.peers_less_than_full_node_danger_boundary, self.channel_set, self.logger) self.assertEqual(self.counter_channel.minor_count, 1) def test_set_no_of_peers_raises_no_alerts_if_decrease_for_full_node_if_outside_danger( self): self.full_node.set_no_of_peers( self.peers_more_than_full_node_danger_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.full_node.set_no_of_peers( self.peers_more_than_full_node_danger_boundary - 1, self.channel_set, self.logger) self.assertTrue(self.counter_channel.no_alerts()) def test_set_no_of_peers_raises_major_alert_if_decrease_for_validator_if_inside_danger( self): self.validator.set_no_of_peers(self.peers_validator_danger_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_no_of_peers( self.peers_less_than_validator_danger_boundary, self.channel_set, self.logger) self.assertEqual(self.counter_channel.major_count, 1) def test_set_no_of_peers_raises_minor_alert_if_decrease_for_validator_if_outside_danger_inside_safe( self): self.validator.set_no_of_peers(self.peers_validator_safe_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_no_of_peers(self.peers_validator_safe_boundary - 1, self.channel_set, self.logger) self.assertEqual(self.counter_channel.minor_count, 1) def test_set_no_of_peers_raises_no_alerts_if_decrease_for_validator_if_outside_safe( self): self.validator.set_no_of_peers( self.peers_more_than_validator_safe_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_no_of_peers( self.peers_more_than_validator_safe_boundary - 1, self.channel_set, self.logger) self.assertEqual(self.counter_channel.minor_count, 0) self.assertEqual(self.counter_channel.major_count, 0) self.assertEqual(self.counter_channel.info_count, 0) self.assertEqual(self.counter_channel.error_count, 0) def test_set_no_of_peers_raises_info_alert_if_increase_for_validator_outside_safe_for_first_time( self): self.validator.set_no_of_peers( self.peers_less_than_validator_safe_boundary, self.channel_set, self.logger) self.counter_channel.reset() # ignore previous alerts self.validator.set_no_of_peers( self.peers_more_than_validator_safe_boundary, self.channel_set, self.logger) self.assertEqual(self.counter_channel.minor_count, 0) self.assertEqual(self.counter_channel.major_count, 0) self.assertEqual(self.counter_channel.info_count, 1) self.assertEqual(self.counter_channel.error_count, 0)
class TestPolkadotApi(unittest.TestCase): @classmethod def setUpClass(cls) -> None: cls.ws_url = 'the_ws' cls.api_endpoint = 'the_api' cls.block_hash = 'the_block_hash' cls.acc_addr = 'the_account_address' cls.validator_id = "the_validator_id" cls.block_no = 1 cls.referendum_index = 2 cls.session_index = 3 cls.auth_index = 4 def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.wrapper = PolkadotApiWrapper(self.logger, self.api_endpoint) self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.params = {'websocket': self.ws_url} def test_api_endpoint_returns_api_endpoint(self): self.assertEqual(self.api_endpoint, self.wrapper.api_endpoint) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_block_hash(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/rpc/chain/getBlockHash' self.params['block_number'] = self.block_no api_call = 'chain/getBlockHash' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_block_hash(self.ws_url, self.block_no)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_finalized_head(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/rpc/chain/getFinalizedHead' api_call = 'chain/getFinalizedHead' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_finalized_head(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_header(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/rpc/chain/getHeader' self.params['hash'] = self.block_hash api_call = 'chain/getHeader' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_header(self.ws_url, self.block_hash)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_system_chain(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/rpc/system/chain' api_call = 'system/chain' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_system_chain(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_system_health(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/rpc/system/health' api_call = 'system/health' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_system_health(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_council_members(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/council/members' api_call = 'council/members' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_council_members(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_council_proposal_count(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/council/proposalCount' api_call = 'council/proposalCount' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_council_proposal_count(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_public_proposal_count(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/democracy/publicPropCount' api_call = 'democracy/publicPropCount' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_public_proposal_count(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_referendum_count(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/democracy/referendumCount' api_call = 'democracy/referendumCount' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_referendum_count(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_referendum_info_of(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/democracy/referendumInfoOf' api_call = 'democracy/referendumInfoOf' self.params['referendum_index'] = self.referendum_index mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_referendum_info_of(self.ws_url, self.referendum_index)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_authored_block(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/imOnline/authoredBlocks' self.params['validator_id'] = self.validator_id self.params['session_index'] = self.session_index api_call = 'imOnline/authoredBlocks' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_authored_blocks(self.ws_url, self.session_index, self.validator_id)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_received_heartbeats(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/imOnline/receivedHeartbeats' self.params['session_index'] = self.session_index self.params['auth_index'] = self.auth_index api_call = 'imOnline/receivedHeartbeats' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_received_heartbeats(self.ws_url, self.session_index, self.auth_index)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_current_index(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/session/currentIndex' api_call = 'session/currentIndex' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_current_index(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_disabled_validators(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/session/disabledValidators' api_call = 'session/disabledValidators' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_disabled_validators(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_session_validators(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/session/validators' api_call = 'session/validators' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_session_validators(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_derive_staking_validators(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/derive/staking/validators' api_call = 'staking/validators' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_derive_staking_validators( self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_eras_stakers(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/staking/erasStakers' self.params['account_id'] = self.acc_addr api_call = 'staking/erasStakers' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_eras_stakers(self.ws_url, self.acc_addr)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_events(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/system/events' self.params['block_hash'] = self.block_hash api_call = 'system/events' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_events(self.ws_url, self.block_hash)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_slash_amount(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/custom/getSlashAmount' self.params['block_hash'] = self.block_hash self.params['account_address'] = self.acc_addr api_call = 'custom/getSlashAmount' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_slash_amount(self.ws_url, self.block_hash, self.acc_addr)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_web_sockets_connected_to_an_api(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/getConnectionsList' api_call = '' mock.api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_web_sockets_connected_to_an_api()) @patch(GET_POLKADOT_JSON_FUNCTION) def test_ping_api(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/pingApi' self.params = {} api_call = '' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.ping_api()) @patch(GET_POLKADOT_JSON_FUNCTION) def test_ping_node(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/pingNode' api_call = '' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.ping_node(self.ws_url)) def test_set_api_as_down_produces_alert_if_api_not_down(self): # By default, API not down # First time round, error alert is produced self.counter_channel.reset() self.wrapper.set_api_as_down("", self.channel_set) self.assertEqual(1, self.counter_channel.error_count) # Second time round, API is already down, so no alerts self.counter_channel.reset() self.wrapper.set_api_as_down("", self.channel_set) self.assertTrue(self.counter_channel.no_alerts()) def test_set_api_as_up_produces_alert_if_api_is_down(self): # By default, API not down # First time round, no alert is produced self.counter_channel.reset() self.wrapper.set_api_as_up("", self.channel_set) self.assertTrue(self.counter_channel.no_alerts()) # In between, we set the api as down self.wrapper.set_api_as_down("", self.channel_set) # API is now down, so info alert is produced self.counter_channel.reset() self.wrapper.set_api_as_up("", self.channel_set) self.assertEqual(1, self.counter_channel.info_count)
class TestPolkadotApi(unittest.TestCase): @classmethod def setUpClass(cls) -> None: cls.ws_url = 'the_ws' cls.api_endpoint = 'the_api' cls.block_hash = 'the_block_hash' cls.acc_addr = 'the_account_address' cls.validator_id = "the_validator_id" cls.block_no = 1 cls.referendum_index = 2 cls.session_index = 3 cls.auth_index = 4 def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.wrapper = PolkadotApiWrapper(self.logger, self.api_endpoint) self.max_time = 15 self.max_time_less = self.max_time - 10 self.max_time_more = self.max_time + 2 self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.params = {'websocket': self.ws_url} def test_api_endpoint_returns_api_endpoint(self): self.assertEqual(self.api_endpoint, self.wrapper.api_endpoint) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_block_hash(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/rpc/chain/getBlockHash' self.params['block_number'] = self.block_no api_call = 'chain/getBlockHash' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_block_hash(self.ws_url, self.block_no)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_finalized_head(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/rpc/chain/getFinalizedHead' api_call = 'chain/getFinalizedHead' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_finalized_head(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_header(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/rpc/chain/getHeader' self.params['hash'] = self.block_hash api_call = 'chain/getHeader' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_header(self.ws_url, self.block_hash)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_system_chain(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/rpc/system/chain' api_call = 'system/chain' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_system_chain(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_system_health(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/rpc/system/health' api_call = 'system/health' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_system_health(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_council_members(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/council/members' api_call = 'council/members' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_council_members(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_council_proposal_count(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/council/proposalCount' api_call = 'council/proposalCount' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_council_proposal_count(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_public_proposal_count(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/democracy/publicPropCount' api_call = 'democracy/publicPropCount' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_public_proposal_count(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_referendum_count(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/democracy/referendumCount' api_call = 'democracy/referendumCount' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_referendum_count(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_referendum_info_of(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/democracy/referendumInfoOf' api_call = 'democracy/referendumInfoOf' self.params['referendum_index'] = self.referendum_index mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_referendum_info_of( self.ws_url, self.referendum_index)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_authored_block(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/imOnline/authoredBlocks' self.params['validator_id'] = self.validator_id self.params['session_index'] = self.session_index api_call = 'imOnline/authoredBlocks' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_authored_blocks( self.ws_url, self.session_index, self.validator_id)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_received_heartbeats(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/imOnline/receivedHeartbeats' self.params['session_index'] = self.session_index self.params['auth_index'] = self.auth_index api_call = 'imOnline/receivedHeartbeats' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_received_heartbeats( self.ws_url, self.session_index, self.auth_index)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_current_index(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/session/currentIndex' api_call = 'session/currentIndex' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_current_index(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_disabled_validators(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/session/disabledValidators' api_call = 'session/disabledValidators' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_disabled_validators(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_session_validators(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/session/validators' api_call = 'session/validators' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_session_validators(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_derive_staking_validators(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/derive/staking/validators' api_call = 'staking/validators' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_derive_staking_validators(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_eras_stakers(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/staking/erasStakers' self.params['account_id'] = self.acc_addr api_call = 'staking/erasStakers' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_eras_stakers(self.ws_url, self.acc_addr)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_active_era(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/staking/activeEra' api_call = 'staking/activeEra' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_active_era(self.ws_url)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_events(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/query/system/events' self.params['block_hash'] = self.block_hash api_call = 'system/events' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_events(self.ws_url, self.block_hash)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_slash_amount(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/custom/getSlashAmount' self.params['block_hash'] = self.block_hash self.params['account_address'] = self.acc_addr api_call = 'custom/getSlashAmount' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_slash_amount( self.ws_url, self.block_hash, self.acc_addr)) @patch(GET_POLKADOT_JSON_FUNCTION) def test_get_web_sockets_connected_to_an_api(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/getConnectionsList' api_call = '' mock.api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_web_sockets_connected_to_an_api()) @patch(GET_POLKADOT_JSON_FUNCTION) def test_ping_api(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/pingApi' self.params = {} api_call = '' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.ping_api()) @patch(GET_POLKADOT_JSON_FUNCTION) def test_ping_node(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/pingNode' api_call = 'pingNode' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.ping_node(self.ws_url)) def test_api_not_down_by_default(self) -> None: self.assertFalse(self.wrapper.is_api_down) def test_set_api_as_down_produces_warning_alert_if_api_not_down( self) -> None: # Test for validator monitors self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(1, self.counter_channel.warning_count) self.assertIsInstance(self.counter_channel.latest_alert, ApiIsDownAlert) # Set API up again, and clear state self.wrapper.set_api_as_up("", self.channel_set) self.counter_channel.reset() # Test for non-validator monitors self.wrapper.set_api_as_down("", False, self.channel_set) self.assertEqual(1, self.counter_channel.warning_count) self.assertIsInstance(self.counter_channel.latest_alert, ApiIsDownAlert) def test_set_api_as_down_produces_no_warning_alert_if_api_down( self) -> None: # Test for validator monitors self.wrapper.set_api_as_down("", True, self.channel_set) self.counter_channel.reset() self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(0, self.counter_channel.warning_count) # Set API up again, and clear state self.wrapper.set_api_as_up("", self.channel_set) self.counter_channel.reset() # Test for non-validator monitors self.wrapper.set_api_as_down("", False, self.channel_set) self.counter_channel.reset() self.wrapper.set_api_as_down("", False, self.channel_set) self.assertEqual(0, self.counter_channel.warning_count) def test_set_api_as_down_sets_api_down(self) -> None: # Test for validator monitors - API previously not down self.wrapper.set_api_as_down("", True, self.channel_set) self.assertTrue(self.wrapper.is_api_down) # Test for validator monitors - API previously down self.wrapper.set_api_as_down("", True, self.channel_set) self.assertTrue(self.wrapper.is_api_down) # Set API up and reset state self.counter_channel.reset() self.wrapper.set_api_as_up("", self.channel_set) # Test for non-validator monitors - API previously not down self.wrapper.set_api_as_down("", False, self.channel_set) self.assertTrue(self.wrapper.is_api_down) # Test for non-validator monitors - API previously down self.wrapper.set_api_as_down("", False, self.channel_set) self.assertTrue(self.wrapper.is_api_down) def test_set_api_as_down_raises_critical_alert_for_val_monitors_if_conditions_are_met( self) -> None: # Declare API as down and start timer. self.wrapper.set_api_as_down("", False, self.channel_set) self.counter_channel.reset() # Enough time passed - no critical alert sent yet sleep(self.max_time_more) self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(1, self.counter_channel.critical_count) self.assertIsInstance(self.counter_channel.latest_alert, ApiIsDownAlert) # Enough time passed - critical alert sent self.counter_channel.reset() self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(0, self.counter_channel.critical_count) # To reset state self.wrapper.set_api_as_up("", self.channel_set) self.counter_channel.reset() # Not enough time passed - no critical alert sent yet self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(0, self.counter_channel.critical_count) self.counter_channel.reset() # Not enough time passed - critical alert sent self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(0, self.counter_channel.critical_count) def test_set_api_as_down_raises_no_critical_alert_for_non_val_monitors( self) -> None: # Not enough time passed self.wrapper.set_api_as_down("", False, self.channel_set) self.assertEqual(0, self.counter_channel.critical_count) self.counter_channel.reset() # Enough time passed sleep(self.max_time_more) self.wrapper.set_api_as_down("", False, self.channel_set) self.assertEqual(0, self.counter_channel.critical_count) def test_set_api_as_up_produces_info_alert_if_api_is_down(self): self.wrapper.set_api_as_down("", True, self.channel_set) self.counter_channel.reset() self.wrapper.set_api_as_up("", self.channel_set) self.assertEqual(1, self.counter_channel.info_count) self.assertIsInstance(self.counter_channel.latest_alert, ApiIsUpAgainAlert) def test_set_api_as_up_produces_no_alert_if_api_is_up(self): self.wrapper.set_api_as_up("", self.channel_set) self.assertTrue(self.counter_channel.no_alerts())
class TestOasisApi(unittest.TestCase): @classmethod def setUpClass(cls) -> None: cls.ws_url = 'the_ws' cls.api_endpoint = 'http://localhost:8688' cls.acc_addr = 'the_account_address' cls.validator_id = "the_validator_id" cls.block_no = 1 def setUp(self) -> None: self.logger = logging.getLogger('dummy') self.node_name = 'dummy_node' self.wrapper = OasisApiWrapper(self.logger) self.max_time = 15 self.max_time_less = self.max_time - 10 self.max_time_more = self.max_time + 2 self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConf) self.params = {'name': self.node_name} @patch(GET_OASIS_JSON_FUNCTION) def test_get_block_header(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/consensus/blockheader' api_call = '' self.params = {'name': self.node_name} mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_block_header(self.api_endpoint, self.node_name)) @patch(GET_OASIS_JSON_FUNCTION) def test_get_is_syncing(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/nodecontroller/synced' api_call = '' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_is_syncing(self.api_endpoint, self.node_name)) @patch(GET_OASIS_JSON_FUNCTION) def test_get_node(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/registry/node' api_call = '' self.params['nodeID'] = self.validator_id mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_node(self.api_endpoint, self.node_name, self.validator_id)) @patch(GET_OASIS_JSON_FUNCTION) def test_get_prometheus_gauge(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/prometheus/gauge' api_call = '' self.params['gauge'] = "peers" mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_prometheus_gauge(self.api_endpoint, self.node_name, "peers")) @patch(GET_OASIS_JSON_FUNCTION) def test_get_consensus_genesis(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/consensus/genesis' api_call = '' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_consensus_genesis(self.api_endpoint, self.node_name)) @patch(GET_OASIS_JSON_FUNCTION) def test_get_consensus_block(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/consensus/block' api_call = '' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_consensus_block(self.api_endpoint, self.node_name)) @patch(GET_OASIS_JSON_FUNCTION) def test_get_block_header_at_height(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/consensus/blockheader' api_call = '' self.params['height'] = self.block_no mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_block_header_height(self.api_endpoint, self.node_name, self.block_no)) @patch(GET_OASIS_JSON_FUNCTION) def test_get_session_validators(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/scheduler/validators' api_call = '' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_session_validators(self.api_endpoint, self.node_name)) @patch(GET_OASIS_JSON_FUNCTION) def test_get_web_sockets_connected_to_an_api(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/getconnectionslist' api_call = '' mock.api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_web_sockets_connected_to_an_api( \ self.api_endpoint)) @patch(GET_OASIS_JSON_FUNCTION) def test_ping_api(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/ping' self.params = {} api_call = '' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.ping_api(self.api_endpoint)) @patch(GET_OASIS_JSON_FUNCTION) def test_get_tendermint_address(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/consensus/pubkeyaddress' self.params = {'consensus_public_key': self.acc_addr} api_call = '' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_tendermint_address(self.api_endpoint, \ self.acc_addr)) @patch(GET_OASIS_JSON_FUNCTION) def test_get_registry_node(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/registry/node' self.params = {'name': self.node_name, 'nodeID': self.acc_addr} api_call = '' mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue(self.wrapper.get_registry_node(self.api_endpoint, \ self.node_name, self.acc_addr)) @patch(GET_OASIS_JSON_FUNCTION) def test_ping_node(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/pingnode' api_call = '' self.params = {'name': self.node_name} mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.ping_node(self.api_endpoint, self.node_name)) @patch(GET_OASIS_JSON_FUNCTION) def test_get_staking_account(self, mock): # Set up mock endpoint = self.api_endpoint + '/api/staking/account' api_call = '' self.params = {'name': self.node_name, 'address': self.acc_addr} mock.side_effect = api_mock_generator(endpoint, self.params, api_call) self.assertTrue( self.wrapper.get_staking_account(self.api_endpoint, self.node_name, self.acc_addr)) def test_set_api_as_down_produces_warning_alert_if_api_not_down_for_val_monitors( self) -> None: self.counter_channel.reset() self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(1, self.counter_channel.warning_count) self.assertIsInstance(self.counter_channel.latest_alert, ApiIsDownAlert) def test_set_api_as_down_produces_no_error_alert_if_api_down_for_val_monitors( self) -> None: self.wrapper.set_api_as_down("", True, self.channel_set) self.counter_channel.reset() self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(0, self.counter_channel.error_count) def test_set_api_as_down_produces_warning_alert_if_api_not_down_for_non_val_monitors( self) -> None: self.counter_channel.reset() self.wrapper.set_api_as_down("", False, self.channel_set) self.assertEqual(1, self.counter_channel.warning_count) self.assertIsInstance(self.counter_channel.latest_alert, ApiIsDownAlert) def test_set_api_as_down_produces_no_error_alert_if_api_down_for_non_val_monitors( self) -> None: self.wrapper.set_api_as_down("", False, self.channel_set) self.counter_channel.reset() self.wrapper.set_api_as_down("", False, self.channel_set) self.assertEqual(0, self.counter_channel.error_count) def test_set_api_as_down_sets_api_down_if_api_not_down_for_val_monitors( self) -> None: self.counter_channel.reset() self.wrapper.set_api_as_down("", True, self.channel_set) self.assertTrue(self.wrapper.is_api_down) def test_api_not_down_by_default(self) -> None: self.assertFalse(self.wrapper.is_api_down) def test_set_api_as_down_sets_api_down_if_api_down_for_non_val_monitors( self) -> None: self.wrapper.set_api_as_down("", False, self.channel_set) self.counter_channel.reset() self.wrapper.set_api_as_down("", False, self.channel_set) self.assertTrue(self.wrapper.is_api_down) def test_set_api_as_down_sets_api_down_if_api_down_for_val_monitors( self) -> None: self.wrapper.set_api_as_down("", True, self.channel_set) self.counter_channel.reset() self.wrapper.set_api_as_down("", True, self.channel_set) self.assertTrue(self.wrapper.is_api_down) def test_set_api_as_down_sets_api_down_if_api_not_down_for_non_val_monitors( self) -> None: self.counter_channel.reset() self.wrapper.set_api_as_down("", False, self.channel_set) self.assertTrue(self.wrapper.is_api_down) def test_set_api_as_down_raises_warning_alert_for_val_monitors_if_enough_time_passed_for_first_time( self) -> None: # To perform did task self.wrapper.set_api_as_up("", self.channel_set) self.counter_channel.reset() sleep(self.max_time_more) self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(1, self.counter_channel.warning_count) self.assertIsInstance(self.counter_channel.latest_alert, ApiIsDownAlert) def test_set_api_as_down_raises_no_critical_alert_for_val_monitors_if_enough_time_passed_for_second_time( self) -> None: # To perform did task self.wrapper.set_api_as_up("", self.channel_set) sleep(self.max_time_more) self.wrapper.set_api_as_down("", True, self.channel_set) self.counter_channel.reset() self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(0, self.counter_channel.critical_count) def test_set_api_as_down_raises_no_critical_alert_for_val_monitors_if_not_enough_time_passed_for_second_time( self) -> None: # To perform did task self.wrapper.set_api_as_up("", self.channel_set) self.wrapper.set_api_as_down("", True, self.channel_set) self.counter_channel.reset() self.wrapper.set_api_as_down("", True, self.channel_set) self.assertEqual(0, self.counter_channel.critical_count) def test_set_api_as_down_raises_no_critical_alert_for_non_val_monitors_if_enough_time_passed_for_first_time( self) -> None: # To perform did task self.wrapper.set_api_as_up("", self.channel_set) sleep(self.max_time_more) self.wrapper.set_api_as_down("", False, self.channel_set) self.assertEqual(0, self.counter_channel.critical_count) def test_set_api_as_down_raises_no_critical_alert_for_non_val_monitors_if_enough_time_passed_for_second_time( self) -> None: # To perform did task self.wrapper.set_api_as_up("", self.channel_set) sleep(self.max_time_more) self.wrapper.set_api_as_down("", False, self.channel_set) self.wrapper.set_api_as_down("", False, self.channel_set) self.assertEqual(0, self.counter_channel.critical_count) def test_set_api_as_down_raises_no_critical_alert_for_non_val_monitors_if_not_enough_time_passed_for_second_time( self) -> None: # To perform did task self.wrapper.set_api_as_up("", self.channel_set) self.wrapper.set_api_as_down("", False, self.channel_set) self.wrapper.set_api_as_down("", False, self.channel_set) self.assertEqual(0, self.counter_channel.critical_count) def test_set_api_as_up_produces_info_alert_if_api_is_down(self): self.wrapper.set_api_as_down("", True, self.channel_set) self.counter_channel.reset() self.wrapper.set_api_as_up("", self.channel_set) self.assertEqual(1, self.counter_channel.info_count) self.assertIsInstance(self.counter_channel.latest_alert, ApiIsUpAgainAlert) def test_set_api_as_up_produces_no_alert_if_api_is_up(self): self.wrapper.set_api_as_up("", self.channel_set) self.assertTrue(self.counter_channel.no_alerts())
class TestChannelSet(unittest.TestCase): def setUp(self) -> None: self.alerter_name = 'testalerter' self.logger = logging.getLogger('dummy') self.counter_channel = CounterChannel(self.logger) self.channel_set = ChannelSet([self.counter_channel], TestInternalConfSomeAlertsDisabled) self.dummy_alert = Alert(AlertCode.TestAlert, 'dummy') self.severities_map_bkp = \ TestInternalConfSomeAlertsDisabled.severities_enabled_map.copy() self.alerts_map_bkp = \ TestInternalConfSomeAlertsDisabled.alerts_enabled_map.copy() @staticmethod def enable_severity(severity: SeverityCode): TestInternalConfSomeAlertsDisabled.severities_enabled_map[ severity.name] = True @staticmethod def disable_severity(severity: SeverityCode): TestInternalConfSomeAlertsDisabled.severities_enabled_map[ severity.name] = False @staticmethod def enable_alert(alert: AlertCode): TestInternalConfSomeAlertsDisabled.alerts_enabled_map[ alert.name] = True @staticmethod def disable_alert(alert: AlertCode): TestInternalConfSomeAlertsDisabled.alerts_enabled_map[ alert.name] = False def tearDown(self) -> None: self.counter_channel.reset() # ignore previous alerts TestInternalConfSomeAlertsDisabled.severities_enabled_map = \ self.severities_map_bkp TestInternalConfSomeAlertsDisabled.alerts_enabled_map = \ self.alerts_map_bkp def test_info_severity_disabled_from_config(self): # As set in test_internal_config_alerts, info is disabled by default self.channel_set.alert_info(self.dummy_alert) self.assertEqual(self.counter_channel.info_count, 0) def test_warning_severity_disabled_from_config(self): # As set in test_internal_config_alerts, warning is disabled by default self.channel_set.alert_warning(self.dummy_alert) self.assertEqual(self.counter_channel.warning_count, 0) def test_critical_severity_enabled_from_config(self): # As set in test_internal_config_alerts, critical is enabled by default self.channel_set.alert_critical(self.dummy_alert) self.assertEqual(self.counter_channel.critical_count, 1) def test_error_severity_enabled_from_config(self): # As set in test_internal_config_alerts, error is enabled by default self.channel_set.alert_error(self.dummy_alert) self.assertEqual(self.counter_channel.error_count, 1) def test_info_severity_does_not_work_if_disabled(self): self.disable_severity(SeverityCode.INFO) self.channel_set.alert_info(self.dummy_alert) self.assertEqual(self.counter_channel.info_count, 0) def test_warning_severity_does_not_work_if_disabled(self): self.disable_severity(SeverityCode.WARNING) self.channel_set.alert_warning(self.dummy_alert) self.assertEqual(self.counter_channel.warning_count, 0) def test_critical_severity_does_not_work_if_disabled(self): self.disable_severity(SeverityCode.CRITICAL) self.channel_set.alert_critical(self.dummy_alert) self.assertEqual(self.counter_channel.critical_count, 0) def test_error_severity_does_not_work_if_disabled(self): self.disable_severity(SeverityCode.ERROR) self.channel_set.alert_error(self.dummy_alert) self.assertEqual(self.counter_channel.error_count, 0) def test_info_severity_works_if_enabled(self): self.enable_severity(SeverityCode.INFO) self.channel_set.alert_info(self.dummy_alert) self.assertEqual(self.counter_channel.info_count, 1) def test_warning_severity_works_if_enabled(self): self.enable_severity(SeverityCode.WARNING) self.channel_set.alert_warning(self.dummy_alert) self.assertEqual(self.counter_channel.warning_count, 1) def test_critical_severity_works_if_enabled(self): self.enable_severity(SeverityCode.CRITICAL) self.channel_set.alert_critical(self.dummy_alert) self.assertEqual(self.counter_channel.critical_count, 1) def test_error_severity_works_if_enabled(self): self.enable_severity(SeverityCode.ERROR) self.channel_set.alert_error(self.dummy_alert) self.assertEqual(self.counter_channel.error_count, 1) def test_alert_works_if_severity_and_alert_enabled_in_config(self): # As set in test_internal_config_alerts, # - info, warning are disabled by default # - critical, error are enabled by default # - test alert code is enabled by default self.channel_set.alert_info(self.dummy_alert) self.channel_set.alert_warning(self.dummy_alert) self.channel_set.alert_critical(self.dummy_alert) self.channel_set.alert_error(self.dummy_alert) self.assertEqual(self.counter_channel.info_count, 0) self.assertEqual(self.counter_channel.warning_count, 0) self.assertEqual(self.counter_channel.critical_count, 1) self.assertEqual(self.counter_channel.error_count, 1) def test_alert_does_not_work_on_any_severity_if_disabled(self): self.disable_alert(self.dummy_alert.alert_code) self.channel_set.alert_info(self.dummy_alert) self.channel_set.alert_warning(self.dummy_alert) self.channel_set.alert_critical(self.dummy_alert) self.channel_set.alert_error(self.dummy_alert) self.assertTrue(self.counter_channel.no_alerts()) def test_alert_works_on_any_severity_if_enabled(self): self.enable_severity(SeverityCode.INFO) self.enable_severity(SeverityCode.WARNING) self.enable_severity(SeverityCode.CRITICAL) self.enable_severity(SeverityCode.ERROR) self.enable_alert(self.dummy_alert.alert_code) self.channel_set.alert_info(self.dummy_alert) self.channel_set.alert_warning(self.dummy_alert) self.channel_set.alert_critical(self.dummy_alert) self.channel_set.alert_error(self.dummy_alert) self.assertEqual(self.counter_channel.info_count, 1) self.assertEqual(self.counter_channel.warning_count, 1) self.assertEqual(self.counter_channel.critical_count, 1) self.assertEqual(self.counter_channel.error_count, 1)