예제 #1
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.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.monitor._internal_conf = TestInternalConf
예제 #2
0
    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], 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.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
예제 #3
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
예제 #4
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
예제 #5
0
    def setUp(self) -> None:
        self.logger = logging.getLogger('dummy')
        self.db = TestInternalConf.redis_test_database
        self.host = 'dummyhost'
        self.port = TestUserConf.redis_port
        self.namespace = 'testnamespace'
        self.redis = RedisApi(self.logger, self.db, self.host,
                              self.port, namespace=self.namespace)

        self.key = 'key'
        self.val = 'val'
        self.time = timedelta.max
예제 #6
0
    def test_set_unsafe_throws_exception_if_incorrect_password(self):
        redis_bad_pass = RedisApi(self.logger, self.db, self.host, self.port,
                                  password='******',
                                  namespace=self.namespace)

        self.redis.set_unsafe(self.key1, self.val1)  # works
        try:
            redis_bad_pass.set_unsafe(self.key1, self.val1)
            self.fail('Expected AuthenticationError to be thrown')
        except AuthenticationError:
            pass
        except ResponseError:
            pass
def test_redis(host: str, port: str, password: str) -> TestOutcome:
    redis = RedisApi(DUMMY_LOGGER, 0, host, int(port),
                     password=password, namespace='')
    try:
        redis.ping_unsafe()
        print('Test completed successfully.')
        return TestOutcome.OK
    except Exception as e:
        print('Something went wrong: {}'.format(e))
        if yn_prompt('Retry Redis setup? (Y/n)\n'):
            return TestOutcome.RestartSetup
        else:
            return TestOutcome.SkipSetup
예제 #8
0
 def setUp(self) -> None:
     self.logger = logging.getLogger('dummy')
     self.db = TestInternalConf.redis_test_database
     self.host = 'dummyhost'
     self.port = 6379
     self.live_check_time_interval = timedelta(seconds=3)
     self.live_check_time_interval_with_error_margin = timedelta(
         seconds=3.5)
     self.redis = RedisApi(
         self.logger,
         self.db,
         self.host,
         self.port,
         live_check_time_interval=self.live_check_time_interval)
예제 #9
0
    def setUpClass(cls) -> None:
        # Same as in setUp(), to avoid running all tests if Redis is offline

        logger = logging.getLogger('dummy')
        db = TestInternalConf.redis_test_database
        host = TestUserConf.redis_host
        port = TestUserConf.redis_port
        password = TestUserConf.redis_password
        redis = RedisApi(logger, db, host, port, password)

        try:
            redis.ping_unsafe()
        except RedisConnectionError:
            raise Exception('Redis is not online.')
예제 #10
0
    def setUp(self) -> None:
        self.logger = logging.getLogger('dummy')
        self.db = TestInternalConf.redis_test_database
        self.host = TestUserConf.redis_host
        self.port = TestUserConf.redis_port
        self.namespace = 'testnamespace'
        self.password = TestUserConf.redis_password
        self.redis = RedisApi(self.logger,
                              self.db,
                              self.host,
                              self.port,
                              password=self.password,
                              namespace=self.namespace)

        # Ping Redis
        try:
            self.redis.ping_unsafe()
        except RedisConnectionError:
            self.fail('Redis is not online.')

        # Clear test database
        self.redis.delete_all_unsafe()

        self.key1 = 'key1'
        self.key2 = 'key2'
        self.key3 = 'key3'
        self.key4 = 'key4'

        self.val1 = 'val1'
        self.val1_bytes = bytes('val1', encoding='utf8')
        self.val2 = 'val2'
        self.val2_bytes = bytes('val2', encoding='utf8')
        self.val3_int = 123
        self.val4 = str(True)
        self.val4_bool = True

        self.time = timedelta(seconds=3)
        self.time_with_error_margin = timedelta(seconds=4)

        self.default_str = 'DEFAULT'
        self.default_int = 789
        self.default_bool = False
예제 #11
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)
예제 #12
0
class TestBlockchainMonitorWithRedis(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        # Same as in setUp(), to avoid running all tests if Redis is offline

        logger = logging.getLogger('dummy')
        db = TestInternalConf.redis_test_database
        host = TestUserConf.redis_host
        port = TestUserConf.redis_port
        password = TestUserConf.redis_password
        redis = RedisApi(logger, db, host, port, password)

        try:
            redis.ping_unsafe()
        except RedisConnectionError:
            raise Exception('Redis is not online.')

    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 test_save_state_saves_alive_key_temporarily(self):
        self.monitor.save_state()

        key = Keys.get_blockchain_monitor_alive(self.monitor_name)
        last_update = self.redis.get(key)
        timeout = self.redis.time_to_live(key)

        self.assertIsNotNone(last_update)
        self.assertEqual(timeout, self.alive_key_timeout)
예제 #13
0
def run() -> None:
    # Check if Redis enabled
    if not UserConf.redis_enabled:
        raise InitialisationException('Redis is not set up. Run the setup '
                                      'script to configure Redis.')

    logger = create_logger(InternalConf.redis_log_file, 'redis',
                           InternalConf.logging_level)

    print('Deleting all Redis keys.')

    # Redis database
    try:
        RedisApi(
            logger,
            InternalConf.redis_database,
            UserConf.redis_host,
            UserConf.redis_port,
            password=UserConf.redis_password,
            namespace=UserConf.unique_alerter_identifier).delete_all_unsafe()
    except Exception as e:
        sys.exit(e)

    # Redis test database
    try:
        RedisApi(
            logger,
            InternalConf.redis_test_database,
            UserConf.redis_host,
            UserConf.redis_port,
            password=UserConf.redis_password,
            namespace=UserConf.unique_alerter_identifier).delete_all_unsafe()
    except Exception as e:
        sys.exit(e)

    print('Done deleting all Redis keys.')
예제 #14
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], 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)

    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)
        key = Keys.get_alive_reminder_mute()
        self.redis.set_for(key, until, hours)
        self.counter_channel.reset()  # ignore previous alerts
        self.par.send_alive_alert()
        self.redis.remove(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)
예제 #15
0
    def setUp(self) -> None:
        self.logger = logging.getLogger('dummy')
        self.db = TestInternalConf.redis_test_database
        self.host = TestUserConf.redis_host
        self.port = TestUserConf.redis_port
        self.password = TestUserConf.redis_password

        self.namespace1 = 'testnamespace1'
        self.namespace2 = 'testnamespace2'

        self.redis = RedisApi(self.logger,
                              self.db,
                              self.host,
                              self.port,
                              self.password,
                              namespace=self.namespace1)
        self.same_namespace = RedisApi(self.logger,
                                       self.db,
                                       self.host,
                                       self.port,
                                       self.password,
                                       namespace=self.namespace1)
        self.different_namespace = RedisApi(self.logger,
                                            self.db,
                                            self.host,
                                            self.port,
                                            self.password,
                                            namespace=self.namespace2)

        # Ping Redis (all of above instances use same host, port, pass)
        try:
            self.redis.ping_unsafe()
        except RedisConnectionError:
            self.fail('Redis is not online.')

        # Clear test database (all of above instances use same database)
        self.redis.delete_all_unsafe()

        self.key1 = 'key1'
        self.key2 = 'key2'

        self.val1 = 'val1'
        self.val1_bytes = bytes('val1', encoding='utf8')
        self.val2 = 'val2'
        self.val2_bytes = bytes('val2', encoding='utf8')
예제 #16
0
class TestNodeMonitorWithRedis(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        # Same as in setUp(), to avoid running all tests if Redis is offline

        logger = logging.getLogger('dummy')
        db = TestInternalConf.redis_test_database
        host = TestUserConf.redis_host
        port = TestUserConf.redis_port
        password = TestUserConf.redis_password
        redis = RedisApi(logger, db, host, port, password)

        try:
            redis.ping_unsafe()
        except RedisConnectionError:
            raise Exception('Redis is not online.')

    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

    def test_load_state_changes_nothing_if_nothing_saved(self) -> None:
        self.monitor.load_state()

        self.assertEqual(NONE, self.monitor._last_height_checked)

    def test_load_state_sets_values_to_saved_values(self) -> None:
        # Set Redis values manually
        key_lh = Keys.get_node_monitor_last_height_checked(self.monitor_name)
        self.redis.set_unsafe(key_lh, self.dummy_last_height_checked)

        # Load the values from Redis
        self.monitor.load_state()

        # Assert
        self.assertEqual(self.dummy_last_height_checked,
                         self.monitor.last_height_checked)

    def test_save_state_sets_values_to_current_values_and_stores_alive_key_temp(
            self) -> None:
        # Set monitor values manually
        self.monitor._last_height_checked = self.dummy_last_height_checked

        # Save the values to Redis
        self.monitor.save_state()

        key_lh = Keys.get_node_monitor_last_height_checked(self.monitor_name)

        # Get last update, and its timeout in Redis
        last_update = self.redis.get(key_lh)
        timeout = self.redis.time_to_live(key_lh)

        # Assert
        self.assertEqual(self.dummy_last_height_checked,
                         self.redis.get_int(key_lh))
        self.assertIsNotNone(last_update)
        self.assertEqual(timeout, self.redis_alive_key_timeout)
예제 #17
0
class TestRedisApiWithRedisOffline(unittest.TestCase):
    def setUp(self) -> None:
        self.logger = logging.getLogger('dummy')
        self.db = TestInternalConf.redis_test_database
        self.host = 'dummyhost'
        self.port = TestUserConf.redis_port
        self.namespace = 'testnamespace'
        self.redis = RedisApi(self.logger,
                              self.db,
                              self.host,
                              self.port,
                              namespace=self.namespace)

        self.key = 'key'
        self.val = 'val'
        self.time = timedelta.max

    def test_add_namespace_adds_namespace(self):
        key = 'some key'
        key_with_namespace = self.namespace + ':' + key

        self.assertEqual(key_with_namespace, self.redis._add_namespace(key))

    def test_remove_namespace_remove_namespace(self):
        key = 'some key'
        key_with_namespace = self.namespace + ':' + key

        self.assertEqual(key, self.redis._remove_namespace(key_with_namespace))

    def test_add_namespace_adds_nothing_if_already_added_namespace(self):
        key = 'some key'
        key_with_namespace = self.namespace + ':' + key

        self.assertEqual(key_with_namespace,
                         self.redis._add_namespace(key_with_namespace))

    def test_remove_namespace_removes_nothing_if_no_namespace(self):
        key = 'some key'

        self.assertEqual(key, self.redis._remove_namespace(key))

    def test_set_unsafe_throws_connection_exception(self):

        try:
            self.redis.set_unsafe(self.key, self.val)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_hset_unsafe_throws_connection_exception(self):

        try:
            hash_name = "dummy_hash"
            self.redis.hset_unsafe(hash_name, self.key, self.val)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_set_multiple_unsafe_throws_connection_exception(self):

        try:
            self.redis.set_multiple_unsafe({self.key: self.val})
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_hset_multiple_unsafe_throws_connection_exception(self):

        try:
            hash_name = "dummy_hash"
            self.redis.hset_multiple_unsafe(hash_name, {self.key: self.val})
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_set_for_unsafe_throws_connection_exception(self):

        try:
            self.redis.set_for_unsafe(self.key, self.val, self.time)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_time_to_live_unsafe_throws_connection_exception(self):

        try:
            self.redis.time_to_live_unsafe(self.key)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_get_unsafe_throws_connection_exception(self):

        try:
            self.redis.get_unsafe(self.key)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_hget_unsafe_throws_connection_exception(self):

        try:
            hash_name = "dummy_hash"
            self.redis.hget_unsafe(hash_name, self.key)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_get_int_unsafe_throws_connection_exception(self):

        try:
            self.redis.get_int_unsafe(self.key)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_hget_int_unsafe_throws_connection_exception(self):

        try:
            hash_name = "dummy_hash"
            self.redis.hget_int_unsafe(hash_name, self.key)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_get_bool_unsafe_throws_connection_exception(self):

        try:
            self.redis.get_bool_unsafe(self.key)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_hget_bool_unsafe_throws_connection_exception(self):

        try:
            hash_name = "dummy_hash"
            self.redis.hget_bool_unsafe(hash_name, self.key)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_exists_unsafe_throws_connection_exception(self):

        try:
            self.redis.exists_unsafe(self.key)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_hexists_unsafe_throws_connection_exception(self):

        try:
            hash_name = "dummy_hash"
            self.redis.hexists_unsafe(hash_name, self.key)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_get_keys_unsafe_throws_connection_exception(self):

        try:
            self.redis.get_keys_unsafe()
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_remove_unsafe_throws_connection_exception(self):

        try:
            self.redis.remove_unsafe(self.key)
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_delete_all_unsafe_throws_connection_exception(self):

        try:
            self.redis.delete_all_unsafe()
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_set_returns_none(self):
        self.assertIsNone(self.redis.set(self.key, self.val))

    def test_hset_returns_none(self):
        hash_name = "dummy_hash"
        self.assertIsNone(self.redis.hset(hash_name, self.key, self.val))

    def test_set_multiple_returns_none(self):
        self.assertIsNone(self.redis.set_multiple({self.key: self.val}))

    def test_hset_multiple_returns_none(self):
        hash_name = "dummy_hash"
        self.assertIsNone(
            self.redis.hset_multiple(hash_name, {self.key: self.val}))

    def test_set_for_returns_none(self):
        self.assertIsNone(self.redis.set_for(self.key, self.val, self.time))

    def test_time_to_live_returns_none(self):
        self.assertIsNone(self.redis.time_to_live(self.key))

    def test_get_returns_none_if_no_default_specified(self):
        self.assertIsNone(self.redis.get(self.key))

    def test_get_returns_default_if_default_specified(self):
        default = 'default'
        self.assertEqual(self.redis.get(self.key, default=default), default)

    def test_hget_returns_none_if_no_default_specified(self):
        hash_name = "dummy_hash"
        self.assertIsNone(self.redis.hget(hash_name, self.key))

    def test_hget_returns_default_if_default_specified(self):
        hash_name = "dummy_hash"
        default = 'default'
        self.assertEqual(self.redis.hget(hash_name, self.key, default=default),
                         default)

    def test_get_int_returns_none_if_no_default_specified(self):
        self.assertIsNone(self.redis.get_int(self.key))

    def test_get_int_returns_default_if_default_specified(self):
        default = 123456
        self.assertEqual(self.redis.get_int(self.key, default=default),
                         default)

    def test_hget_int_returns_none_if_no_default_specified(self):
        hash_name = "dummy_hash"
        self.assertIsNone(self.redis.hget_int(hash_name, self.key))

    def test_hget_int_returns_default_if_default_specified(self):
        hash_name = "dummy_hash"
        default = 123456
        self.assertEqual(
            self.redis.hget_int(hash_name, self.key, default=default), default)

    def test_get_bool_returns_none_if_no_default_specified(self):
        self.assertIsNone(self.redis.get_bool(self.key))

    def test_get_bool_returns_default_if_default_specified(self):
        default = True
        self.assertEqual(self.redis.get_bool(self.key, default=default),
                         default)

    def test_hget_bool_returns_none_if_no_default_specified(self):
        hash_name = "dummy_hash"
        self.assertIsNone(self.redis.hget_bool(hash_name, self.key))

    def test_hget_bool_returns_default_if_default_specified(self):
        hash_name = "dummy_hash"
        default = True
        self.assertEqual(
            self.redis.hget_bool(hash_name, self.key, default=default),
            default)

    def test_exists_returns_false(self):
        self.assertFalse(self.redis.exists(self.key))

    def test_hexists_returns_false(self):
        hash_name = "dummy_hash"
        self.assertFalse(self.redis.hexists(hash_name, self.key))

    def test_get_keys_returns_empty_list(self):
        self.assertListEqual(self.redis.get_keys(), [])

    def test_remove_returns_none(self):
        self.assertIsNone(self.redis.remove(self.key))

    def test_delete_all_returns_none(self):
        self.assertIsNone(self.redis.delete_all())

    def test_ping_unsafe_throws_connection_exception(self):

        try:
            self.redis.ping_unsafe()
            self.fail('Expected RedisConnectionError exception to be thrown.')
        except RedisConnectionError:
            pass

    def test_second_safe_command_faster_to_throw_than_first_when_offline(self):

        start_1 = time.perf_counter()
        self.redis.set(self.key, self.val)
        elapsed_1 = time.perf_counter() - start_1

        start_2 = time.perf_counter()
        self.redis.set(self.key, self.val)
        elapsed_2 = time.perf_counter() - start_2

        # first executon is more than 10 times slower than second execution
        self.assertGreater(elapsed_1, elapsed_2 * 10)
예제 #18
0
class TestBlockchainWithRedis(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        # Same as in setUp(), to avoid running all tests if Redis is offline

        logger = logging.getLogger('dummy')
        db = TestInternalConf.redis_test_database
        host = TestUserConf.redis_host
        port = TestUserConf.redis_port
        password = TestUserConf.redis_password
        redis = RedisApi(logger, db, host, port, password)

        try:
            redis.ping_unsafe()
        except RedisConnectionError:
            raise Exception('Redis is not online.')

    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], 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.blockchain = Blockchain(self.blockchain_name, self.redis)
        self.dummy_referendum_count = 10
        self.dummy_council_prop_count = 10
        self.dummy_public_prop_count = 10
        self.dummy_validator_set_size = 120

    def test_load_state_changes_nothing_if_nothing_saved(self):
        self.blockchain.load_state(self.logger)

        self.assertIsNone(self.blockchain.validator_set_size)
        self.assertIsNone(self.blockchain.public_prop_count)
        self.assertIsNone(self.blockchain.council_prop_count)
        self.assertIsNone(self.blockchain.validator_set_size)

    def test_load_state_sets_values_to_saved_values(self):
        # Set Redis values manually
        hash_name = Keys.get_hash_blockchain(self.blockchain.name)
        self.redis.hset_multiple_unsafe(
            hash_name, {
                Keys.get_blockchain_referendum_count(self.blockchain.name):
                self.dummy_referendum_count,
                Keys.get_blockchain_public_prop_count(self.blockchain.name):
                self.dummy_public_prop_count,
                Keys.get_blockchain_council_prop_count(self.blockchain.name):
                self.dummy_council_prop_count,
                Keys.get_blockchain_validator_set_size(self.blockchain.name):
                self.dummy_validator_set_size,
            })

        # Load the Redis values
        self.blockchain.load_state(self.logger)

        # Assert
        self.assertEqual(self.blockchain.referendum_count,
                         self.dummy_referendum_count)
        self.assertEqual(self.blockchain.public_prop_count,
                         self.dummy_public_prop_count)
        self.assertEqual(self.blockchain.council_prop_count,
                         self.dummy_council_prop_count)
        self.assertEqual(self.blockchain.validator_set_size,
                         self.dummy_validator_set_size)

    def test_save_state_sets_values_to_current_values(self):
        # Set blockchain values manually
        self.blockchain.set_referendum_count(self.dummy_referendum_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_public_prop_count(self.dummy_public_prop_count,
                                              self.channel_set, self.logger)
        self.blockchain.set_validator_set_size(self.dummy_validator_set_size,
                                               self.channel_set, self.logger)

        # Save the values to Redis
        self.blockchain.save_state(self.logger)

        # Assert
        hash_name = Keys.get_hash_blockchain(self.blockchain.name)
        self.assertEqual(
            self.redis.hget_int_unsafe(
                hash_name,
                Keys.get_blockchain_referendum_count(self.blockchain.name)),
            self.dummy_referendum_count)
        self.assertEqual(
            self.redis.hget_int_unsafe(
                hash_name,
                Keys.get_blockchain_public_prop_count(self.blockchain.name)),
            self.dummy_public_prop_count)
        self.assertEqual(
            self.redis.hget_int_unsafe(
                hash_name,
                Keys.get_blockchain_council_prop_count(self.blockchain.name)),
            self.dummy_council_prop_count)
        self.assertEqual(
            self.redis.hget_int_unsafe(
                hash_name,
                Keys.get_blockchain_validator_set_size(self.blockchain.name)),
            self.dummy_validator_set_size)
예제 #19
0
class TestRedisApiWithRedisOnline(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        # Same as in setUp(), to avoid running all tests if Redis is offline

        logger = logging.getLogger('dummy')
        db = TestInternalConf.redis_test_database
        host = TestUserConf.redis_host
        port = TestUserConf.redis_port
        password = TestUserConf.redis_password
        redis = RedisApi(logger, db, host, port, password=password)

        # Ping Redis
        try:
            redis.ping_unsafe()
        except RedisConnectionError:
            raise Exception('Redis is not online.')

    def setUp(self) -> None:
        self.logger = logging.getLogger('dummy')
        self.db = TestInternalConf.redis_test_database
        self.host = TestUserConf.redis_host
        self.port = TestUserConf.redis_port
        self.namespace = 'testnamespace'
        self.password = TestUserConf.redis_password
        self.redis = RedisApi(self.logger,
                              self.db,
                              self.host,
                              self.port,
                              password=self.password,
                              namespace=self.namespace)

        # Ping Redis
        try:
            self.redis.ping_unsafe()
        except RedisConnectionError:
            self.fail('Redis is not online.')

        # Clear test database
        self.redis.delete_all_unsafe()

        self.key1 = 'key1'
        self.key2 = 'key2'
        self.key3 = 'key3'
        self.key4 = 'key4'

        self.val1 = 'val1'
        self.val1_bytes = bytes('val1', encoding='utf8')
        self.val2 = 'val2'
        self.val2_bytes = bytes('val2', encoding='utf8')
        self.val3_int = 123
        self.val4 = str(True)
        self.val4_bool = True

        self.time = timedelta(seconds=3)
        self.time_with_error_margin = timedelta(seconds=4)

        self.default_str = 'DEFAULT'
        self.default_int = 789
        self.default_bool = False

    def tearDown(self) -> None:
        self.redis.delete_all_unsafe()

    def test_set_unsafe_throws_exception_if_incorrect_password(self):
        redis_bad_pass = RedisApi(self.logger,
                                  self.db,
                                  self.host,
                                  self.port,
                                  password='******',
                                  namespace=self.namespace)

        self.redis.set_unsafe(self.key1, self.val1)  # works
        try:
            redis_bad_pass.set_unsafe(self.key1, self.val1)
            self.fail('Expected AuthenticationError to be thrown')
        except AuthenticationError:
            pass

    def test_set_unsafe_sets_the_specified_key_to_the_specified_value(self):
        self.redis.set_unsafe(self.key1, self.val1)
        self.assertEqual(self.redis.get_unsafe(self.key1), self.val1_bytes)

    def test_set_unsafe_throws_exception_if_invalid_type(self):
        try:
            self.redis.set_unsafe(self.key1, True)
            self.fail('Expected DataError exception to be thrown.')
        except DataError:
            pass

    def test_hset_unsafe_throws_exception_if_incorrect_password(self):
        redis_bad_pass = RedisApi(self.logger,
                                  self.db,
                                  self.host,
                                  self.port,
                                  password='******',
                                  namespace=self.namespace)

        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key1, self.val1)  # works
        try:
            redis_bad_pass.hset_unsafe(hash_name, self.key1, self.val1)
            self.fail('Expected AuthenticationError to be thrown')
        except AuthenticationError:
            pass

    def test_hset_unsafe_sets_the_specified_key_to_the_specified_value(self):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key1, self.val1)
        self.assertEqual(self.redis.hget_unsafe(hash_name, self.key1),
                         self.val1_bytes)

    def test_hset_unsafe_throws_exception_if_invalid_type(self):
        try:
            hash_name = "dummy_hash"
            self.redis.hset_unsafe(hash_name, self.key1, True)
            self.fail('Expected DataError exception to be thrown.')
        except DataError:
            pass

    def test_set_multiple_unsafe_sets_multiple_key_value_pairs(self):
        self.redis.set_multiple_unsafe({
            self.key1: self.val1,
            self.key2: self.val2
        })
        self.assertEqual(self.redis.get_unsafe(self.key1), self.val1_bytes)
        self.assertEqual(self.redis.get_unsafe(self.key2), self.val2_bytes)

    def test_hset_multiple_unsafe_sets_multiple_key_value_pairs(self):
        hash_name = "dummy_hash"
        self.redis.hset_multiple_unsafe(hash_name, {
            self.key1: self.val1,
            self.key2: self.val2
        })
        self.assertEqual(self.redis.hget_unsafe(hash_name, self.key1),
                         self.val1_bytes)
        self.assertEqual(self.redis.hget_unsafe(hash_name, self.key2),
                         self.val2_bytes)

    def test_set_for_unsafe_temporarily_sets_specified_key_value_pair(self):
        self.redis.set_for_unsafe(self.key1, self.val1, self.time)
        self.assertEqual(self.redis.get_unsafe(self.key1), self.val1_bytes)

        sleep(self.time_with_error_margin.seconds)
        self.assertNotEqual(self.redis.get_unsafe(self.key1), self.val1_bytes)

    def test_time_to_live_unsafe_returns_None_if_key_does_not_exist(self):
        self.redis.set(self.key1, self.val1)

        self.assertIsNone(self.redis.time_to_live_unsafe(self.key1))

    def test_time_to_live_unsafe_returns_None_if_key_does_not_have_timeout(
            self):
        self.assertIsNone(self.redis.time_to_live_unsafe(self.key1))

    def test_time_to_live_unsafe_returns_correct_timeout_if_set(self):
        self.redis.set_for_unsafe(self.key1, self.val1, self.time)

        self.assertEqual(self.time.seconds,
                         self.redis.time_to_live_unsafe(self.key1))

    def test_get_unsafe_returns_default_for_unset_key(self):
        self.assertEqual(
            self.redis.get_unsafe(self.key1, default=self.default_str),
            self.default_str)

    def test_get_unsafe_returns_set_value(self):
        self.redis.set_unsafe(self.key1, self.val1)
        self.assertEqual(
            self.redis.get_unsafe(self.key1, default=self.default_str),
            self.val1_bytes)

    def test_get_unsafe_returns_none_for_none_string(self):
        self.redis.set_unsafe(self.key1, 'None')
        self.assertIsNone(
            self.redis.get_unsafe(self.key1, default=self.default_str))

    def test_hget_unsafe_returns_default_for_unset_key(self):
        hash_name = "dummy_hash"
        self.assertEqual(
            self.redis.hget_unsafe(hash_name,
                                   self.key1,
                                   default=self.default_str), self.default_str)

    def test_hget_unsafe_returns_set_value(self):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key1, self.val1)
        self.assertEqual(
            self.redis.hget_unsafe(hash_name,
                                   self.key1,
                                   default=self.default_str), self.val1_bytes)

    def test_hget_unsafe_returns_none_for_none_string(self):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key1, 'None')
        self.assertIsNone(
            self.redis.hget_unsafe(hash_name,
                                   self.key1,
                                   default=self.default_str))

    def test_get_int_unsafe_returns_set_integer(self):
        self.redis.set_unsafe(self.key3, self.val3_int)
        self.assertEqual(
            self.redis.get_int_unsafe(self.key3, default=self.default_int),
            self.val3_int)

    def test_get_int_unsafe_returns_default_for_unset_key(self):
        self.assertEqual(
            self.redis.get_int_unsafe(self.key3, default=self.default_int),
            self.default_int)

    def test_get_int_unsafe_returns_default_for_non_integer_value(self):
        self.redis.set_unsafe(self.key2, self.val2)
        self.assertEqual(
            self.redis.get_int_unsafe(self.key2, default=self.default_int),
            self.default_int)

    def test_hget_int_unsafe_returns_set_integer(self):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key3, self.val3_int)
        self.assertEqual(
            self.redis.hget_int_unsafe(hash_name,
                                       self.key3,
                                       default=self.default_int),
            self.val3_int)

    def test_hget_int_unsafe_returns_default_for_unset_key(self):
        hash_name = "dummy_hash"
        self.assertEqual(
            self.redis.hget_int_unsafe(hash_name,
                                       self.key3,
                                       default=self.default_int),
            self.default_int)

    def test_hget_int_unsafe_returns_default_for_non_integer_value(self):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key2, self.val2)
        self.assertEqual(
            self.redis.hget_int_unsafe(hash_name,
                                       self.key2,
                                       default=self.default_int),
            self.default_int)

    def test_get_bool_unsafe_returns_set_boolean(self):
        self.redis.set_unsafe(self.key4, self.val4)
        self.assertEqual(
            self.redis.get_bool_unsafe(self.key4, default=self.default_bool),
            self.val4_bool)

    def test_get_bool_unsafe_returns_default_for_unset_key(self):
        self.assertEqual(
            self.redis.get_bool_unsafe(self.key4, default=self.default_bool),
            self.default_bool)

    def test_get_bool_unsafe_returns_false_for_non_boolean_value(self):
        self.redis.set_unsafe(self.key1, self.val1)
        self.assertFalse(
            self.redis.get_bool_unsafe(self.key1, default=self.default_bool))

    def test_hget_bool_unsafe_returns_set_boolean(self):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key4, self.val4)
        self.assertEqual(
            self.redis.hget_bool_unsafe(hash_name,
                                        self.key4,
                                        default=self.default_bool),
            self.val4_bool)

    def test_hget_bool_unsafe_returns_default_for_unset_key(self):
        hash_name = "dummy_hash"
        self.assertEqual(
            self.redis.hget_bool_unsafe(hash_name,
                                        self.key4,
                                        default=self.default_bool),
            self.default_bool)

    def test_hget_bool_unsafe_returns_false_for_non_boolean_value(self):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key1, self.val1)
        self.assertFalse(
            self.redis.hget_bool_unsafe(hash_name,
                                        self.key1,
                                        default=self.default_bool))

    def test_exists_unsafe_returns_true_if_exists(self):
        self.redis.set_unsafe(self.key1, self.val1)
        self.assertTrue(self.redis.exists_unsafe(self.key1))

    def test_exists_unsafe_returns_false_if_not_exists(self):
        self.assertFalse(self.redis.exists_unsafe(self.key1))

    def test_hexists_unsafe_returns_true_if_exists(self):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key1, self.val1)
        self.assertTrue(self.redis.hexists_unsafe(hash_name, self.key1))

    def test_hexists_unsafe_returns_false_if_not_exists(self):
        hash_name = "dummy_hash"
        self.assertFalse(self.redis.hexists_unsafe(hash_name, self.key1))

    def test_get_keys_unsafe_returns_empty_list_if_no_keys(self):
        keys_list = self.redis.get_keys_unsafe()
        self.assertListEqual(keys_list, [])

    def test_get_keys_unsafe_returns_list_with_all_keys(self):
        self.redis.set_unsafe(self.key1, self.val1)
        self.redis.set_unsafe(self.key2, self.val2)
        self.redis.set_unsafe(self.key3, self.val3_int)

        keys_list = self.redis.get_keys_unsafe()
        self.assertSetEqual(set(keys_list), {self.key1, self.key2, self.key3})
        # Set is used just in case the keys list is unordered

    def test_get_keys_unsafe_gets_key_that_matches_specific_pattern(self):
        self.redis.set_unsafe(self.key1, self.val1)
        self.redis.set_unsafe(self.key2, self.val2)
        self.redis.set_unsafe(self.key3, self.val3_int)

        keys_list = self.redis.get_keys_unsafe(self.key1)
        self.assertListEqual(keys_list, [self.key1])

        keys_list = self.redis.get_keys_unsafe(self.key2)
        self.assertListEqual(keys_list, [self.key2])

        keys_list = self.redis.get_keys_unsafe(self.key3)
        self.assertListEqual(keys_list, [self.key3])

    def test_get_keys_unsafe_gets_only_keys_that_match_prefix_pattern(self):
        prefixed_key1 = 'aaa' + self.key1
        prefixed_key2 = 'bbb' + self.key2
        prefixed_key3 = 'aa' + self.key3
        self.redis.set_unsafe(prefixed_key1, self.val1)
        self.redis.set_unsafe(prefixed_key2, self.val2)
        self.redis.set_unsafe(prefixed_key3, self.val3_int)

        keys_list = self.redis.get_keys_unsafe('aa*')
        self.assertSetEqual(set(keys_list), {prefixed_key1, prefixed_key3})

    def test_remove_unsafe_does_nothing_if_key_does_not_exists(self):
        self.redis.remove_unsafe(self.key1)

    def test_remove_unsafe_removes_key_if_key_exists(self):
        self.redis.set_unsafe(self.key1, self.val1)
        self.assertTrue(self.redis.exists_unsafe(self.key1))

        self.redis.remove_unsafe(self.key1)
        self.assertFalse(self.redis.exists_unsafe(self.key1))

    def test_delete_all_unsafe_does_nothing_if_no_keys_exist(self):
        self.redis.delete_all_unsafe()

    def test_delete_all_unsafe_removes_keys_if_they_exist(self):
        self.redis.set_unsafe(self.key1, self.val1)
        self.redis.set_unsafe(self.key2, self.val2)
        self.assertTrue(self.redis.exists_unsafe(self.key1))
        self.assertTrue(self.redis.exists_unsafe(self.key2))

        self.redis.delete_all_unsafe()
        self.assertFalse(self.redis.exists_unsafe(self.key1))
        self.assertFalse(self.redis.exists_unsafe(self.key2))

    def test_set_sets_the_specified_key_to_the_specified_value(self):
        self.redis.set(self.key1, self.val1)
        self.assertEqual(self.redis.get(self.key1), self.val1_bytes)

    def test_set_returns_none_if_invalid_type(self):
        self.assertIsNone(self.redis.set(self.key1, True))

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_set_returns_none_if_redis_down(self, _):
        self.assertIsNone(self.redis.set(self.key1, self.val1))
        self.assertFalse(self.redis.exists_unsafe(self.key1))

    def test_hset_sets_the_specified_key_to_the_specified_value(self):
        hash_name = "dummy_hash"
        self.redis.hset(hash_name, self.key1, self.val1)
        self.assertEqual(self.redis.hget(hash_name, self.key1),
                         self.val1_bytes)

    def test_hset_returns_none_if_invalid_type(self):
        hash_name = "dummy_hash"
        self.assertIsNone(self.redis.hset(hash_name, self.key1, True))

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_hset_returns_none_if_redis_down(self, _):
        hash_name = "dummy_hash"
        self.assertIsNone(self.redis.hset(hash_name, self.key1, self.val1))
        self.assertFalse(self.redis.hexists_unsafe(hash_name, self.key1))

    def test_set_multiple_sets_multiple_key_value_pairs(self):
        self.redis.set_multiple({self.key1: self.val1, self.key2: self.val2})
        self.assertEqual(self.redis.get(self.key1), self.val1_bytes)
        self.assertEqual(self.redis.get(self.key2), self.val2_bytes)

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_set_multiple_returns_none_and_nothing_set_if_redis_down(self, _):
        self.assertIsNone(
            self.redis.set_multiple({
                self.key1: self.val1,
                self.key2: self.val2
            }))
        self.assertFalse(self.redis.exists_unsafe(self.key1))
        self.assertFalse(self.redis.exists_unsafe(self.key2))

    def test_hset_multiple_sets_multiple_key_value_pairs(self):
        hash_name = "dummy_hahh"
        self.redis.hset_multiple(hash_name, {
            self.key1: self.val1,
            self.key2: self.val2
        })
        self.assertEqual(self.redis.hget(hash_name, self.key1),
                         self.val1_bytes)
        self.assertEqual(self.redis.hget(hash_name, self.key2),
                         self.val2_bytes)

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_hset_multiple_returns_none_and_nothing_set_if_redis_down(self, _):
        hash_name = "dummy_dash"
        self.assertIsNone(
            self.redis.hset_multiple(hash_name, {
                self.key1: self.val1,
                self.key2: self.val2
            }))
        self.assertFalse(self.redis.hexists_unsafe(hash_name, self.key1))
        self.assertFalse(self.redis.hexists_unsafe(hash_name, self.key2))

    def test_set_for_temporarily_sets_specified_key_value_pair(self):
        self.redis.set_for(self.key1, self.val1, self.time)
        self.assertEqual(self.redis.get(self.key1), self.val1_bytes)

        sleep(self.time_with_error_margin.seconds)
        self.assertNotEqual(self.redis.get(self.key1), self.val1_bytes)

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_set_for_returns_none_and_nothing_set_if_redis_down(self, _):
        self.assertIsNone(self.redis.set_for(self.key1, self.val1, self.time))
        self.assertFalse(self.redis.exists_unsafe(self.key1))

    def test_time_to_live_returns_correct_timeout_when_set(self):
        self.redis.set_for(self.key1, self.val1, self.time)

        self.assertEqual(self.redis.time_to_live(self.key1), self.time.seconds)

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_time_to_live_returns_none_if_redis_down(self, _):
        self.assertIsNone(self.redis.time_to_live(self.key1))

    def test_get_returns_default_for_unset_key(self):
        self.assertEqual(self.redis.get(self.key1, default=self.default_str),
                         self.default_str)

    def test_get_returns_set_value(self):
        self.redis.set(self.key1, self.val1)
        self.assertEqual(self.redis.get(self.key1, default=self.default_str),
                         self.val1_bytes)

    def test_get_returns_none_for_none_string(self):
        self.redis.set(self.key1, 'None')
        self.assertIsNone(self.redis.get(self.key1, default=self.default_str))

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_get_returns_default_if_redis_down(self, _):
        self.redis.set_unsafe(self.key1, self.val1)
        self.assertEqual(self.redis.get(self.key1, default=self.default_str),
                         self.default_str)

    def test_hget_returns_default_for_unset_key(self):
        hash_name = "dummy_hash"
        self.assertEqual(
            self.redis.hget(hash_name, self.key1, default=self.default_str),
            self.default_str)

    def test_hget_returns_set_value(self):
        hash_name = "dummy_hash"
        self.redis.hset(hash_name, self.key1, self.val1)
        self.assertEqual(
            self.redis.hget(hash_name, self.key1, default=self.default_str),
            self.val1_bytes)

    def test_hget_returns_none_for_none_string(self):
        hash_name = "dummy_hash"
        self.redis.hset(hash_name, self.key1, 'None')
        self.assertIsNone(
            self.redis.hget(hash_name, self.key1, default=self.default_str))

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_hget_returns_default_if_redis_down(self, _):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key1, self.val1)
        self.assertEqual(
            self.redis.hget(hash_name, self.key1, default=self.default_str),
            self.default_str)

    def test_get_int_returns_set_integer(self):
        self.redis.set(self.key3, self.val3_int)
        self.assertEqual(
            self.redis.get_int(self.key3, default=self.default_int),
            self.val3_int)

    def test_get_int_returns_default_for_unset_key(self):
        self.assertEqual(
            self.redis.get_int(self.key3, default=self.default_int),
            self.default_int)

    def test_get_int_returns_default_for_non_integer_value(self):
        self.redis.set(self.key2, self.val2)
        self.assertEqual(
            self.redis.get_int(self.key2, default=self.default_int),
            self.default_int)

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_get_int_returns_default_if_redis_down(self, _):
        self.redis.set_unsafe(self.key3, self.val3_int)
        self.assertEqual(
            self.redis.get_int(self.key3, default=self.default_int),
            self.default_int)

    def test_hget_int_returns_set_integer(self):
        hash_name = "dummy_hash"
        self.redis.hset(hash_name, self.key3, self.val3_int)
        self.assertEqual(
            self.redis.hget_int(hash_name, self.key3,
                                default=self.default_int), self.val3_int)

    def test_hget_int_returns_default_for_unset_key(self):
        hash_name = "dummy_hash"
        self.assertEqual(
            self.redis.hget_int(hash_name, self.key3,
                                default=self.default_int), self.default_int)

    def test_hget_int_returns_default_for_non_integer_value(self):
        hash_name = "dummy_hash"
        self.redis.hset(hash_name, self.key2, self.val2)
        self.assertEqual(
            self.redis.hget_int(hash_name, self.key2,
                                default=self.default_int), self.default_int)

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_hget_int_returns_default_if_redis_down(self, _):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key3, self.val3_int)
        self.assertEqual(
            self.redis.hget_int(hash_name, self.key3,
                                default=self.default_int), self.default_int)

    def test_get_bool_returns_set_boolean(self):
        self.redis.set(self.key4, self.val4)
        self.assertEqual(
            self.redis.get_bool(self.key4, default=self.default_bool),
            self.val4_bool)

    def test_get_bool_returns_default_for_unset_key(self):
        self.assertEqual(
            self.redis.get_bool(self.key4, default=self.default_bool),
            self.default_bool)

    def test_get_bool_returns_false_for_non_boolean_value(self):
        self.redis.set(self.key1, self.val1)
        self.assertFalse(
            self.redis.get_bool(self.key1, default=self.default_bool))

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_get_bool_returns_default_if_redis_down(self, _):
        self.redis.set_unsafe(self.key4, self.val4)
        self.assertEqual(
            self.redis.get_bool(self.key4, default=self.default_bool),
            self.default_bool)

    def test_hget_bool_returns_set_boolean(self):
        hash_name = "dummy_hash"
        self.redis.hset(hash_name, self.key4, self.val4)
        self.assertEqual(
            self.redis.hget_bool(hash_name,
                                 self.key4,
                                 default=self.default_bool), self.val4_bool)

    def test_hget_bool_returns_default_for_unset_key(self):
        hash_name = "dummy_hash"
        self.assertEqual(
            self.redis.hget_bool(hash_name,
                                 self.key4,
                                 default=self.default_bool), self.default_bool)

    def test_hget_bool_returns_false_for_non_boolean_value(self):
        hash_name = "dummy_hash"
        self.redis.hset(hash_name, self.key1, self.val1)
        self.assertFalse(
            self.redis.hget_bool(hash_name,
                                 self.key1,
                                 default=self.default_bool))

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_hget_bool_returns_default_if_redis_down(self, _):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key4, self.val4)
        self.assertEqual(
            self.redis.hget_bool(hash_name,
                                 self.key4,
                                 default=self.default_bool), self.default_bool)

    def test_exists_returns_true_if_exists(self):
        self.redis.set(self.key1, self.val1)
        self.assertTrue(self.redis.exists(self.key1))

    def test_exists_returns_false_if_not_exists(self):
        self.assertFalse(self.redis.exists(self.key1))

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_exists_returns_false_if_redis_down(self, _):
        self.redis.set_unsafe(self.key1, self.val1)
        self.assertFalse(self.redis.exists(self.key1))

    def test_hexists_returns_true_if_exists(self):
        hash_name = "dummy_hash"
        self.redis.hset(hash_name, self.key1, self.val1)
        self.assertTrue(self.redis.hexists(hash_name, self.key1))

    def test_hexists_returns_false_if_not_exists(self):
        hash_name = "dummy_hash"
        self.assertFalse(self.redis.hexists(hash_name, self.key1))

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_hexists_returns_false_if_redis_down(self, _):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key1, self.val1)
        self.assertFalse(self.redis.hexists(hash_name, self.key1))

    def test_get_keys_returns_empty_list_if_no_keys(self):
        keys_list = self.redis.get_keys()
        self.assertListEqual(keys_list, [])

    def test_get_keys_returns_list_with_all_keys(self):
        self.redis.set_unsafe(self.key1, self.val1)
        self.redis.set_unsafe(self.key2, self.val2)
        self.redis.set_unsafe(self.key3, self.val3_int)

        keys_list = self.redis.get_keys()
        self.assertSetEqual(set(keys_list), {self.key1, self.key2, self.key3})
        # Set is used just in case the keys list is unordered

    def test_get_keys_gets_key_that_matches_specific_pattern(self):
        self.redis.set_unsafe(self.key1, self.val1)
        self.redis.set_unsafe(self.key2, self.val2)
        self.redis.set_unsafe(self.key3, self.val3_int)

        keys_list = self.redis.get_keys(self.key1)
        self.assertListEqual(keys_list, [self.key1])

        keys_list = self.redis.get_keys(self.key2)
        self.assertListEqual(keys_list, [self.key2])

        keys_list = self.redis.get_keys(self.key3)
        self.assertListEqual(keys_list, [self.key3])

    def test_get_keys_gets_only_keys_that_match_prefix_pattern(self):
        prefixed_key1 = 'aaa' + self.key1
        prefixed_key2 = 'bbb' + self.key2
        prefixed_key3 = 'aa' + self.key3
        self.redis.set_unsafe(prefixed_key1, self.val1)
        self.redis.set_unsafe(prefixed_key2, self.val2)
        self.redis.set_unsafe(prefixed_key3, self.val3_int)

        keys_list = self.redis.get_keys('aa*')
        self.assertSetEqual(set(keys_list), {prefixed_key1, prefixed_key3})

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_get_keys_returns_empty_set_if_redis_down(self, _):
        self.redis.set_unsafe(self.key1, self.val1)
        self.redis.set_unsafe(self.key2, self.val2)
        self.redis.set_unsafe(self.key3, self.val3_int)

        keys_list = self.redis.get_keys()
        self.assertSetEqual(set(keys_list), set())

    def test_remove_does_nothing_if_key_does_not_exists(self):
        self.redis.remove(self.key1)

    def test_remove_removes_key_if_key_exists(self):
        self.redis.set(self.key1, self.val1)
        self.assertTrue(self.redis.exists(self.key1))

        self.redis.remove(self.key1)
        self.assertFalse(self.redis.exists(self.key1))

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_remove_returns_none_if_redis_down(self, _):
        self.redis.set_unsafe(self.key1, self.val1)
        self.assertTrue(self.redis.exists_unsafe(self.key1))

        self.assertIsNone(self.redis.remove(self.key1))
        self.assertTrue(self.redis.exists_unsafe(self.key1))

    def test_delete_all_does_nothing_if_no_keys_exist(self):
        self.redis.delete_all()

    def test_delete_all_removes_keys_if_they_exist(self):
        self.redis.set(self.key1, self.val1)
        self.redis.set(self.key2, self.val2)
        self.assertTrue(self.redis.exists(self.key1))
        self.assertTrue(self.redis.exists(self.key2))

        self.redis.delete_all()
        self.assertFalse(self.redis.exists(self.key1))
        self.assertFalse(self.redis.exists(self.key2))

    @patch(REDIS_RECENTLY_DOWN_FUNCTION, return_value=True)
    def test_delete_all_returns_none_and_deletes_nothing_if_redis_down(
            self, _):
        self.redis.set_unsafe(self.key1, self.val1)
        self.redis.set_unsafe(self.key2, self.val2)
        self.assertTrue(self.redis.exists_unsafe(self.key1))
        self.assertTrue(self.redis.exists_unsafe(self.key2))

        self.assertIsNone(self.redis.delete_all())
        self.assertTrue(self.redis.exists_unsafe(self.key1))
        self.assertTrue(self.redis.exists_unsafe(self.key2))

    def test_ping_unsafe_returns_true(self):
        self.assertTrue(self.redis.ping_unsafe())
예제 #20
0
class TestRedisApiLiveAndDownFeaturesWithRedisOffline(unittest.TestCase):
    def setUp(self) -> None:
        self.logger = logging.getLogger('dummy')
        self.db = TestInternalConf.redis_test_database
        self.host = 'dummyhost'
        self.port = 6379
        self.live_check_time_interval = timedelta(seconds=3)
        self.live_check_time_interval_with_error_margin = timedelta(
            seconds=3.5)
        self.redis = RedisApi(
            self.logger,
            self.db,
            self.host,
            self.port,
            live_check_time_interval=self.live_check_time_interval)

    def test_is_live_returns_true_by_default(self):
        self.assertTrue(self.redis.is_live)

    def test_set_as_live_changes_is_live_to_true(self):
        self.redis._is_live = False
        self.assertFalse(self.redis.is_live)

        self.redis._set_as_live()
        self.assertTrue(self.redis._is_live)

    def test_set_as_live_leaves_is_live_as_true_if_already_true(self):
        self.redis._is_live = True
        self.assertTrue(self.redis.is_live)

        self.redis._set_as_live()
        self.assertTrue(self.redis._is_live)

    def test_set_as_down_changes_is_live_to_false(self):
        self.redis._set_as_down()
        self.assertFalse(self.redis.is_live)

    def test_set_as_down_leaves_is_live_as_false_if_already_false(self):
        self.redis._is_live = False
        self.assertFalse(self.redis.is_live)

        self.redis._set_as_down()
        self.assertFalse(self.redis.is_live)

    def test_allowed_to_use_by_default(self):
        # noinspection PyBroadException
        try:
            self.redis._do_not_use_if_recently_went_down()
        except Exception:
            self.fail('Expected to be allowed to use Redis.')

    def test_not_allowed_to_use_if_set_as_down_and_within_time_interval(self):
        self.redis._set_as_down()
        # noinspection PyBroadException
        try:
            self.redis._do_not_use_if_recently_went_down()
            self.fail('Expected to not be allowed to use Redis.')
        except Exception:
            pass

    def test_allowed_to_use_if_set_as_down_and_within_time_interval(self):
        self.redis._set_as_down()
        sleep(self.live_check_time_interval_with_error_margin.seconds)
        # noinspection PyBroadException
        try:
            self.redis._do_not_use_if_recently_went_down()
        except Exception:
            self.fail('Expected to be allowed to use Redis.')
예제 #21
0
class TestRedisNamespaceWithRedisOnline(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        # Same as in setUp(), to avoid running all tests if Redis is offline

        logger = logging.getLogger('dummy')
        db = TestInternalConf.redis_test_database
        host = TestUserConf.redis_host
        port = TestUserConf.redis_port
        password = TestUserConf.redis_password
        redis = RedisApi(logger, db, host, port, password)

        # Ping Redis
        try:
            redis.ping_unsafe()
        except RedisConnectionError:
            raise Exception('Redis is not online.')

    def setUp(self) -> None:
        self.logger = logging.getLogger('dummy')
        self.db = TestInternalConf.redis_test_database
        self.host = TestUserConf.redis_host
        self.port = TestUserConf.redis_port
        self.password = TestUserConf.redis_password

        self.namespace1 = 'testnamespace1'
        self.namespace2 = 'testnamespace2'

        self.redis = RedisApi(self.logger,
                              self.db,
                              self.host,
                              self.port,
                              self.password,
                              namespace=self.namespace1)
        self.same_namespace = RedisApi(self.logger,
                                       self.db,
                                       self.host,
                                       self.port,
                                       self.password,
                                       namespace=self.namespace1)
        self.different_namespace = RedisApi(self.logger,
                                            self.db,
                                            self.host,
                                            self.port,
                                            self.password,
                                            namespace=self.namespace2)

        # Ping Redis (all of above instances use same host, port, pass)
        try:
            self.redis.ping_unsafe()
        except RedisConnectionError:
            self.fail('Redis is not online.')

        # Clear test database (all of above instances use same database)
        self.redis.delete_all_unsafe()

        self.key1 = 'key1'
        self.key2 = 'key2'

        self.val1 = 'val1'
        self.val1_bytes = bytes('val1', encoding='utf8')
        self.val2 = 'val2'
        self.val2_bytes = bytes('val2', encoding='utf8')

    def tearDown(self) -> None:
        self.redis.delete_all_unsafe()
        self.different_namespace.delete_all_unsafe()

    def test_set_uses_namespace_internally(self):
        self.redis.set_unsafe(self.key1, self.val1)

        # Use raw Redis command to get, to bypass automatically-added namespace
        get_value = self.redis._redis.get(self.namespace1 + ':' + self.key1)

        self.assertEqual(get_value, self.val1_bytes)

    def test_hset_uses_namespace_internally(self):
        hash_name = "dummy_hash"
        self.redis.hset_unsafe(hash_name, self.key1, self.val1)

        # Use raw Redis command to get, to bypass automatically-added namespace
        get_value = self.redis._redis.hget(self.namespace1 + ':' + hash_name,
                                           self.key1)

        self.assertEqual(get_value, self.val1_bytes)

    def test_get_uses_namespace_internally(self):
        # Use raw Redis command to set, to bypass automatically-added namespace
        self.redis._redis.set(self.namespace1 + ':' + self.key1, self.val1)

        get_value = self.redis.get_unsafe(self.key1)
        self.assertEqual(get_value, self.val1_bytes)

    def test_hget_uses_namespace_internally(self):
        hash_name = "dummy_hash"

        # Use raw Redis command to set, to bypass automatically-added namespace
        self.redis._redis.hset(self.namespace1 + ':' + hash_name, self.key1,
                               self.val1)

        get_value = self.redis.hget_unsafe(hash_name, self.key1)
        self.assertEqual(get_value, self.val1_bytes)

    def test_redis_api_with_same_namespace_has_access_to_same_store(self):
        self.redis.set_unsafe(self.key1, self.val1)

        self.assertEqual(self.same_namespace.get_unsafe(self.key1),
                         self.val1_bytes)

    def test_redis_api_with_different_namespace_has_separate_store(self):
        self.redis.set_unsafe(self.key1, self.val1)

        self.assertNotEqual(self.different_namespace.get_unsafe(self.key1),
                            self.val1_bytes)
예제 #22
0
        'commands_telegram',
        InternalConf.logging_level,
        rotating=True)

    # Set file location where all alerts will be stored
    log_file_alerts = InternalConf.alerts_log_file

    # Sets wrapper to query oasis api connected to nodes
    oasis_api_data_wrapper = OasisApiWrapper(logger_general)

    # Set Redis Object if it's enabled, pass the created Logger together
    # with details of the Redis server to the Redis API Object
    if UserConf.redis_enabled:
        REDIS = RedisApi(logger_redis,
                         InternalConf.redis_database,
                         UserConf.redis_host,
                         UserConf.redis_port,
                         password=UserConf.redis_password,
                         namespace=UserConf.unique_alerter_identifier)
    else:
        REDIS = None

    # Set MONGO Object if it's enabled, pass the created Logger together
    # with details of the MONGO databse to the MONGO API Object
    if UserConf.mongo_enabled:
        MONGO = MongoApi(logger_mongo,
                         UserConf.mongo_db_name,
                         UserConf.mongo_host,
                         UserConf.mongo_port,
                         username=UserConf.mongo_user,
                         password=UserConf.mongo_pass)
    else:
예제 #23
0
class TestGitHubMonitorWithRedis(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        # Same as in setUp(), to avoid running all tests if Redis is offline

        logger = logging.getLogger('dummy')
        db = TestInternalConf.redis_test_database
        host = TestUserConf.redis_host
        port = TestUserConf.redis_port
        password = TestUserConf.redis_password
        redis = RedisApi(logger, db, host, port, password)

        try:
            redis.ping_unsafe()
        except RedisConnectionError:
            raise Exception('Redis is not online.')

    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.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.monitor._internal_conf = TestInternalConf

    def test_load_state_changes_nothing_if_nothing_saved(self):
        self.monitor.load_state()

        self.assertIsNone(self.monitor._prev_no_of_releases)

    def test_load_state_sets_values_to_saved_values(self):
        # Set Redis values manually
        key = Keys.get_github_releases(self.repo_name)
        self.redis.set_unsafe(key, 10)

        # Load the values from Redis
        self.monitor.load_state()

        # Assert
        self.assertEqual(10, self.monitor._prev_no_of_releases)

    def test_save_state_sets_values_to_current_values(self):
        # Set monitor values manually
        self.monitor._prev_no_of_releases = 10

        # Save the values to Redis
        self.monitor.save_state()

        # Assert
        key = Keys.get_github_releases(self.repo_name)
        self.assertEqual(10, self.redis.get_int(key))

    def test_save_state_sets_nothing_if_no_previous_state(self):
        # Save the values to Redis
        self.monitor.save_state()

        # Assert
        key = Keys.get_github_releases(self.repo_name)
        self.assertIsNone(self.redis.get_int(key))