2
0

locking.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import time
  2. import pytest
  3. from ..locking import get_id, TimeoutTimer, ExclusiveLock , UpgradableLock, LockRoster, ADD, REMOVE, SHARED, EXCLUSIVE
  4. ID1 = "foo", 1, 1
  5. ID2 = "bar", 2, 2
  6. def test_id():
  7. hostname, pid, tid = get_id()
  8. assert isinstance(hostname, str)
  9. assert isinstance(pid, int)
  10. assert isinstance(tid, int)
  11. assert len(hostname) > 0
  12. assert pid > 0
  13. class TestTimeoutTimer:
  14. def test_timeout(self):
  15. timeout = 0.5
  16. t = TimeoutTimer(timeout).start()
  17. assert not t.timed_out()
  18. time.sleep(timeout * 1.5)
  19. assert t.timed_out()
  20. def test_notimeout_sleep(self):
  21. timeout, sleep = None, 0.5
  22. t = TimeoutTimer(timeout, sleep).start()
  23. assert not t.timed_out_or_sleep()
  24. assert time.time() >= t.start_time + 1 * sleep
  25. assert not t.timed_out_or_sleep()
  26. assert time.time() >= t.start_time + 2 * sleep
  27. @pytest.fixture()
  28. def lockpath(tmpdir):
  29. return str(tmpdir.join('lock'))
  30. class TestExclusiveLock:
  31. def test_checks(self, lockpath):
  32. with ExclusiveLock(lockpath, timeout=1) as lock:
  33. assert lock.is_locked() and lock.by_me()
  34. def test_acquire_break_reacquire(self, lockpath):
  35. lock = ExclusiveLock(lockpath, id=ID1).acquire()
  36. lock.break_lock()
  37. with ExclusiveLock(lockpath, id=ID2):
  38. pass
  39. def test_timeout(self, lockpath):
  40. with ExclusiveLock(lockpath, id=ID1):
  41. with pytest.raises(ExclusiveLock.LockTimeout):
  42. ExclusiveLock(lockpath, id=ID2, timeout=0.1).acquire()
  43. class TestUpgradableLock:
  44. def test_shared(self, lockpath):
  45. lock1 = UpgradableLock(lockpath, exclusive=False, id=ID1).acquire()
  46. lock2 = UpgradableLock(lockpath, exclusive=False, id=ID2).acquire()
  47. assert len(lock1._roster.get(SHARED)) == 2
  48. assert len(lock1._roster.get(EXCLUSIVE)) == 0
  49. lock1.release()
  50. lock2.release()
  51. def test_exclusive(self, lockpath):
  52. with UpgradableLock(lockpath, exclusive=True, id=ID1) as lock:
  53. assert len(lock._roster.get(SHARED)) == 0
  54. assert len(lock._roster.get(EXCLUSIVE)) == 1
  55. def test_upgrade(self, lockpath):
  56. with UpgradableLock(lockpath, exclusive=False) as lock:
  57. lock.upgrade()
  58. lock.upgrade() # NOP
  59. assert len(lock._roster.get(SHARED)) == 0
  60. assert len(lock._roster.get(EXCLUSIVE)) == 1
  61. def test_downgrade(self, lockpath):
  62. with UpgradableLock(lockpath, exclusive=True) as lock:
  63. lock.downgrade()
  64. lock.downgrade() # NOP
  65. assert len(lock._roster.get(SHARED)) == 1
  66. assert len(lock._roster.get(EXCLUSIVE)) == 0
  67. def test_break(self, lockpath):
  68. lock = UpgradableLock(lockpath, exclusive=True, id=ID1).acquire()
  69. lock.break_lock()
  70. assert len(lock._roster.get(SHARED)) == 0
  71. assert len(lock._roster.get(EXCLUSIVE)) == 0
  72. with UpgradableLock(lockpath, exclusive=True, id=ID2):
  73. pass
  74. @pytest.fixture()
  75. def rosterpath(tmpdir):
  76. return str(tmpdir.join('roster'))
  77. class TestLockRoster:
  78. def test_empty(self, rosterpath):
  79. roster = LockRoster(rosterpath)
  80. empty = roster.load()
  81. roster.save(empty)
  82. assert empty == {}
  83. def test_modify_get(self, rosterpath):
  84. roster1 = LockRoster(rosterpath, id=ID1)
  85. assert roster1.get(SHARED) == set()
  86. roster1.modify(SHARED, ADD)
  87. assert roster1.get(SHARED) == {ID1, }
  88. roster2 = LockRoster(rosterpath, id=ID2)
  89. roster2.modify(SHARED, ADD)
  90. assert roster2.get(SHARED) == {ID1, ID2, }
  91. roster1 = LockRoster(rosterpath, id=ID1)
  92. roster1.modify(SHARED, REMOVE)
  93. assert roster1.get(SHARED) == {ID2, }
  94. roster2 = LockRoster(rosterpath, id=ID2)
  95. roster2.modify(SHARED, REMOVE)
  96. assert roster2.get(SHARED) == set()