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()
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)
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 })
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()
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()
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()
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')
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()
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')