Skip to content

Commit

Permalink
Add test case for timing out acquiring a lock
Browse files Browse the repository at this point in the history
Added test for context manager lock acquisition timeout. Also fixed
the code to no longer call release when failing to acquire the lock.
  • Loading branch information
stealthycoin committed Dec 13, 2018
1 parent d52bff1 commit 66dc7f6
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/lynk/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ def __call__(self, lease_duration=20, timeout_seconds=300):

@contextmanager
def _context_manager(self, lease_duration, max_wait_seconds):
self.acquire(
lease_duration=lease_duration,
max_wait_seconds=max_wait_seconds,
)
try:
self.acquire(
lease_duration=lease_duration,
max_wait_seconds=max_wait_seconds,
)
yield
finally:
self.release()
Expand Down
15 changes: 15 additions & 0 deletions tests/unit/test_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from lynk.techniques import BaseTechnique
from lynk.refresh import LockRefresherFactory
from lynk.refresh import LockRefresher
from lynk.exceptions import LockNotGrantedError


@pytest.fixture
Expand Down Expand Up @@ -53,6 +54,20 @@ def test_context_manager_does_acquire_and_release(self, create_lock):
tech.acquire.assert_called_with('lock name', 20, max_wait_seconds=300)
tech.release.assert_called_with('lock name')

def test_lock_not_granted_does_escape_context_manager(self, create_lock):
# The context manager swallows errors, its important that the
# LockNotGrantedError escapes this otherwise it could be silenced and
# the with block would exceute and operate on a resource protected by
# the lock, even though the lock acquisition failed.
# Also the release should not be called, since the acquire failed.
lock, tech, _ = create_lock()
tech.acquire.side_effect = LockNotGrantedError()
with pytest.raises(LockNotGrantedError):
with lock():
pass
tech.acquire.assert_called_with('lock name', 20, max_wait_seconds=300)
tech.release.assert_not_called()

def test_acquire_does_create_and_start_refresher(self, create_lock):
lock, tech, refresher_factory = create_lock(refresher=True)
mock_refresher = mock.Mock(spec=LockRefresher)
Expand Down

0 comments on commit 66dc7f6

Please sign in to comment.