Exemple #1
0
    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
            }
        }
Exemple #2
0
    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
Exemple #3
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.par = PeriodicAliveReminder(timedelta(), self.channel_set, None)
Exemple #4
0
    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}
Exemple #5
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])

        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)
Exemple #7
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],
                                      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
Exemple #11
0
    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
Exemple #13
0
    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
Exemple #14
0
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)
Exemple #15
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
Exemple #16
0
    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
Exemple #17
0
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)
Exemple #18
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)
Exemple #19
0
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)
Exemple #21
0
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)
Exemple #22
0
    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)
Exemple #23
0
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)
Exemple #24
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)
Exemple #25
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.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())
Exemple #27
0
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)