def test_refuses_concurrency(self): """ :func:`non_concurrently` raises :obj:`ConcurrentError` when the key is already locked. """ self._add_lock('the-key') eff = Effect(Error(RuntimeError('foo'))) non_c_eff = non_concurrently(self.locks, 'the-key', eff) self.assertRaises( ConcurrentError, sync_perform, _get_dispatcher(), non_c_eff) self.assertEqual(self._get_locks(), pset(['the-key']))
def test_cleans_up_on_exception(self): """ When the effect results in error, the key is still removed from the locked set. """ dispatcher = _get_dispatcher() eff = Effect(Error(RuntimeError('foo!'))) non_c_eff = non_concurrently(self.locks, 'the-key', eff) e = self.assertRaises(RuntimeError, sync_perform, dispatcher, non_c_eff) self.assertEqual(str(e), 'foo!') self.assertEqual(self._get_locks(), pset([]))
def test_success(self): """ :func:`non_concurrently` returns the result of the passed effect, and adds the ``key`` to the ``locks`` while executing. """ dispatcher = _get_dispatcher() def execute_stuff(): self.assertEqual(self._get_locks(), pset(['the-key'])) return 'foo' eff = Effect(Func(execute_stuff)) non_c_eff = non_concurrently(self.locks, 'the-key', eff) self.assertEqual(sync_perform(dispatcher, non_c_eff), 'foo') # after the effect completes, its lock is released self.assertEqual(self._get_locks(), pset([]))