Beispiel #1
0
    def test_should_not_release_read_lock_when_not_owner_on_delete(
            self, mock_uuid, mock_redis):
        # given
        mock_uuid.return_value = 'QWERTY'
        pipeline_verify_secret = MagicMock()
        pipeline_delete_lock = MagicMock()
        pipeline_verify_secret.return_value.get.return_value = \
            b'{"timestamp": 123456, "secret": ["QWERTY"], "exclusive": false}'
        pipeline_delete_lock.return_value.get.return_value = \
            b'{"timestamp": 123456, "secret": ["otherSecret"], "exclusive": false}'
        verify_secret_pipeline_cm = MagicMock()
        delete_lock_pipeline_cm = MagicMock()
        verify_secret_pipeline_cm.__enter__ = pipeline_verify_secret
        delete_lock_pipeline_cm.__enter__ = pipeline_delete_lock
        mock_redis.return_value.pipeline.side_effect = (
            verify_secret_pipeline_cm, delete_lock_pipeline_cm)
        lock = RedisReadLock('TestLock', prefix='RedisLockUnitTest')

        # when
        with self.assertRaisesRegex(RuntimeError, 'release unlocked lock'):
            lock.release()

        # then
        pipeline_delete_lock.return_value.watch.assert_called_once_with(
            'RedisLockUnitTest:lock:TestLock')
        pipeline_delete_lock.return_value.delete.assert_not_called()
        pipeline_delete_lock.return_value.set.assert_not_called()
Beispiel #2
0
    def test_should_retry_when_key_changed_on_delete(self, mock_uuid,
                                                     mock_redis):
        # given
        mock_uuid.return_value = 'QWERTY'
        pipeline_verify_secret = MagicMock()
        pipeline_delete_lock = MagicMock()
        pipeline_verify_secret.return_value.get.return_value = \
            b'{"timestamp": 123456, "secret": ["QWERTY"], "exclusive": false}'
        pipeline_delete_lock.return_value.get.return_value = \
            b'{"timestamp": 123456, "secret": ["QWERTY"], "exclusive": false}'
        pipeline_delete_lock.return_value.delete.side_effect = (WatchError(),
                                                                WatchError(),
                                                                1)
        verify_secret_pipeline_cm = MagicMock()
        delete_lock_pipeline_cm = MagicMock()
        verify_secret_pipeline_cm.__enter__ = pipeline_verify_secret
        delete_lock_pipeline_cm.__enter__ = pipeline_delete_lock
        mock_redis.return_value.pipeline.side_effect = (
            verify_secret_pipeline_cm, delete_lock_pipeline_cm,
            delete_lock_pipeline_cm, delete_lock_pipeline_cm)
        lock = RedisReadLock('TestLock', prefix='RedisLockUnitTest')

        # when
        lock.release()

        # then
        self.assertEqual(pipeline_verify_secret.return_value.watch.call_count,
                         1)
        self.assertEqual(pipeline_delete_lock.return_value.watch.call_count, 3)
Beispiel #3
0
    def test_should_only_remove_secret_on_release_when_multiple_read_locks(
            self, mock_uuid, mock_redis):
        # given
        mock_uuid.return_value = 'QWERTY'
        pipeline_verify_secret = MagicMock()
        pipeline_delete_lock = MagicMock()
        pipeline_verify_secret.return_value.get.return_value = \
            b'{"timestamp": 123456, "secret": ["QWERTY", "secretData"], "exclusive": false}'
        pipeline_delete_lock.return_value.get.return_value = \
            b'{"timestamp": 123456, "secret": ["QWERTY", "secretData"], "exclusive": false}'
        pipeline_delete_lock.return_value.ttl.return_value = 102
        verify_secret_pipeline_cm = MagicMock()
        delete_lock_pipeline_cm = MagicMock()
        verify_secret_pipeline_cm.__enter__ = pipeline_verify_secret
        delete_lock_pipeline_cm.__enter__ = pipeline_delete_lock
        mock_redis.return_value.pipeline.side_effect = (
            verify_secret_pipeline_cm, delete_lock_pipeline_cm)
        lock = RedisReadLock('TestLock', prefix='RedisLockUnitTest')

        # when
        lock.release()

        # then
        pipeline_delete_lock.return_value.watch.assert_called_once_with(
            'RedisLockUnitTest:lock:TestLock')
        pipeline_delete_lock.return_value.delete.assert_not_called()
        pipeline_delete_lock.return_value.set.assert_called_once_with(
            'RedisLockUnitTest:lock:TestLock', ex=102, value=ANY)
        value = pipeline_delete_lock.return_value.set.mock_calls[0][2].get(
            'value')
        self.assertDictEqual(loads(value), {
            'timestamp': 123456,
            'secret': ['secretData'],
            'exclusive': False
        })
Beispiel #4
0
    def test_should_release_single_read_lock_when_others_not_exists(
            self, mock_uuid, mock_redis):
        # given
        mock_uuid.return_value = 'QWERTY'
        pipeline_verify_secret = MagicMock()
        pipeline_delete_lock = MagicMock()
        pipeline_verify_secret.return_value.get.return_value = \
            b'{"timestamp": 123456, "secret": ["QWERTY"], "exclusive": false}'
        pipeline_delete_lock.return_value.get.return_value = \
            b'{"timestamp": 123456, "secret": ["QWERTY"], "exclusive": false}'
        verify_secret_pipeline_cm = MagicMock()
        delete_lock_pipeline_cm = MagicMock()
        verify_secret_pipeline_cm.__enter__ = pipeline_verify_secret
        delete_lock_pipeline_cm.__enter__ = pipeline_delete_lock
        mock_redis.return_value.pipeline.side_effect = (
            verify_secret_pipeline_cm, delete_lock_pipeline_cm)
        lock = RedisReadLock('TestLock', prefix='RedisLockUnitTest')

        # when
        lock.release()

        # then
        pipeline_delete_lock.return_value.watch.assert_called_once_with(
            'RedisLockUnitTest:lock:TestLock')
        pipeline_delete_lock.return_value.delete.assert_called_once_with(
            'RedisLockUnitTest:lock:TestLock')
        pipeline_delete_lock.return_value.execute.assert_called_once_with()
Beispiel #5
0
    def test_should_repeat_query_when_value_changed_in_meantime(
            self, mock_time, mock_uuid, mock_redis):
        # given
        mock_uuid.return_value = 'QWERTY'
        pipeline = MagicMock()
        pipeline.return_value.get.return_value = None
        mock_redis.return_value.pipeline.return_value.__enter__ = pipeline
        lock = RedisReadLock('TestLock', prefix='RedisLockUnitTest')
        mock_time.return_value = 123456
        pipeline.return_value.set.side_effect = (WatchError(), WatchError(),
                                                 'OK')

        # when
        result = lock.acquire()

        # then
        self.assertTrue(result)
        self.assertEqual(pipeline.return_value.watch.call_count, 3)
        self.assertEqual(pipeline.return_value.set.call_count, 3)
        value = pipeline.return_value.set.mock_calls[0][2].get('value')
        self.assertDictEqual(loads(value), {
            'timestamp': 123456,
            'secret': ['QWERTY'],
            'exclusive': False
        })
        pipeline.return_value.execute.assert_called_once_with()
Beispiel #6
0
    def test_should_acquire_read_lock_when_other_non_exclusive_exists(
            self, mock_time, mock_uuid, mock_redis):
        # given
        mock_uuid.return_value = 'QWERTY'
        pipeline = MagicMock()
        pipeline.return_value.get.return_value =\
            b'{"timestamp": 123456, "secret": ["secret", "other"], "exclusive": false}'
        mock_redis.return_value.pipeline.return_value.__enter__ = pipeline
        lock = RedisReadLock('TestLock', prefix='RedisLockUnitTest')
        mock_time.return_value = 123456

        # when
        result = lock.acquire()

        # then
        self.assertTrue(result)
        pipeline.return_value.watch.assert_called_once_with(
            'RedisLockUnitTest:lock:TestLock')
        pipeline.return_value.set.assert_called_once_with(
            'RedisLockUnitTest:lock:TestLock', ex=None, value=ANY)
        value = pipeline.return_value.set.mock_calls[0][2].get('value')
        self.assertDictEqual(loads(value), {
            'timestamp': 123456,
            'secret': ANY,
            'exclusive': False
        })
        secrets = loads(value).get('secret')
        self.assertSetEqual(set(secrets), {'QWERTY', 'secret', 'other'})
        pipeline.return_value.execute.assert_called_once_with()
Beispiel #7
0
    def test_should_not_release_read_lock_when_no_lock_exists(
            self, mock_uuid, mock_redis):
        # given
        mock_uuid.return_value = 'QWERTY'
        pipeline_verify_secret = MagicMock()
        pipeline_verify_secret.return_value.get.return_value = None
        verify_secret_pipeline_cm = MagicMock()
        verify_secret_pipeline_cm.__enter__ = pipeline_verify_secret
        mock_redis.return_value.pipeline.return_value = verify_secret_pipeline_cm
        lock = RedisReadLock('TestLock', prefix='RedisLockUnitTest')

        # when
        with self.assertRaisesRegex(RuntimeError,
                                    'cannot release un-acquired lock'):
            lock.release()

        # then
        pipeline_verify_secret.return_value.watch.assert_called_once_with(
            'RedisLockUnitTest:lock:TestLock')
Beispiel #8
0
    def test_should_not_acquire_read_lock_when_non_exclusive_lock_exists_with_non_list_secret(
            self, mock_time, mock_uuid, mock_redis):
        # given
        mock_uuid.return_value = 'QWERTY'
        pipeline = MagicMock()
        pipeline.return_value.get.return_value = \
            b'{"timestamp": 123456, "secret": "secretData", "exclusive": false}'
        mock_redis.return_value.pipeline.return_value.__enter__ = pipeline
        lock = RedisReadLock('TestLock', prefix='RedisLockUnitTest')
        mock_time.return_value = 123456

        # when
        result = lock.acquire(blocking=False)

        # then
        self.assertFalse(result)
        pipeline.return_value.watch.assert_called_once_with(
            'RedisLockUnitTest:lock:TestLock')
        pipeline.return_value.set.assert_not_called()
Beispiel #9
0
    def test_should_not_release_read_lock_when_not_owner(
            self, mock_uuid, mock_redis):
        # given
        mock_uuid.return_value = 'QWERTY'
        pipeline_verify_secret = MagicMock()
        pipeline_verify_secret.return_value.get.return_value = \
            b'{"timestamp": 123456, "secret": ["otherLock"], "exclusive": false}'
        verify_secret_pipeline_cm = MagicMock()
        verify_secret_pipeline_cm.__enter__ = pipeline_verify_secret
        mock_redis.return_value.pipeline.return_value = verify_secret_pipeline_cm
        lock = RedisReadLock('TestLock', prefix='RedisLockUnitTest')

        # when
        with self.assertRaisesRegex(RuntimeError,
                                    'cannot release un-acquired lock'):
            lock.release()

        # then
        pipeline_verify_secret.return_value.watch.assert_called_once_with(
            'RedisLockUnitTest:lock:TestLock')