def test_multiple_semaphores_remainder(): """ Verify that we can acquire and release locks to different semaphores """ with throttle_client(b"[semaphores]\nA=1\nB=1\nC=1") as client: with lock(client, "A"): assert 0 == client.remainder("A") with lock(client, "B"): assert 0 == client.remainder("B") with lock(client, "C"): assert 0 == client.remainder("C") assert 1 == client.remainder("A") assert 1 == client.remainder("B") assert 1 == client.remainder("C")
def test_error_on_leasing_unknown_semaphore(): """ Verify what error we receive than acquiring a semaphore for a ressource unknown to the server. """ with throttle(b"[semaphores]") as url: with pytest.raises(Exception, match=r"Unknown semaphore"): with lock(url, "Unknown"): pass
def acquire_lease_concurrent(client: Client): # Simulate expired peer: Create peer with bogus id. peer = PeerWithHeartbeat(client=client, id=42) set_local_peer(BASE_URL, peer) # Lock must now restore the peer, after hitting `Unknown Peer` and acquire the # lock to A afterwards. with lock(BASE_URL, "A", timeout=timedelta(seconds=10)): nonlocal acquired_lease acquired_lease = True
def test_remainder(): """ Verify that we can acquire a lock to semaphore and release it """ with throttle_client(b"[semaphores]\nA=1") as client: assert 1 == client.remainder("A") with lock(client, "A"): assert 0 == client.remainder("A") assert 1 == client.remainder("A")
def test_lock_count_larger_one(): """ Assert that locks with a count > 1, decrement the semaphore count accordingly """ with throttle_client(b"[semaphores]\nA=5") as client: with lock(client, "A", count=3): assert client.remainder("A") == 2 assert client.remainder("A") == 5
def test_exception(): """ Assert that lock is freed in the presence of exceptions in the client code """ with throttle_client(b"[semaphores]\nA=1") as client: try: with lock(client, "A"): raise Exception() except Exception: assert client.remainder("A") == 1
def test_try_lock(): """ Assert that a call to lock raises Timout Exception if pending to long """ with throttle(b"[semaphores]\nA=1") as url: # We hold the lease, all following calls are going to block first = Peer.from_server_url(url) first.acquire("A") with pytest.raises(Timeout): with lock(BASE_URL, "A", timeout=timedelta(seconds=1)): pass
def test_nested_locks(): """ Nested locks should be well behaved """ with throttle_client(b"[semaphores]\nA=1\nB=1") as client: with lock(client, "A") as peer: assert client.remainder("A") == 0 assert client.remainder("B") == 1 with lock(client, "B", peer=peer): assert client.remainder("A") == 0 assert client.remainder("B") == 0 assert client.remainder("A") == 0 assert client.remainder("B") == 1 assert client.remainder("A") == 1 assert client.remainder("B") == 1
def test_try_lock(): """ Assert that a call to lock raises Timout Exception if pending to long """ with throttle_client(b"[semaphores]\nA=1") as client: # We hold the lease, all following calls are going to block first = client.new_peer() client.acquire(first, "A") with pytest.raises(Timeout): with lock(client, "A", timeout=timedelta(seconds=1)): pass
def test_keep_lease_alive_beyond_expiration(): """ Validates that a heartbeat keeps the lease alive beyond the initial expiration time. """ with throttle_client(b"[semaphores]\nA=1") as client: client.expiration_time = timedelta(seconds=1) with lock(client, "A", heartbeat_interval=timedelta(seconds=0)) as _: sleep(1.5) # Evens though enough time has passed, our lease should not be # expired, thanks to the heartbeat. assert client.remove_expired() == 0
def test_nested_locks(): """ Nested locks should be well behaved """ with throttle(b"[semaphores]\nA={ max=1, level=1 }\nB={ max=1, level=0 }" ) as url: client = Client(url) with lock(url, "A"): assert client.remainder("A") == 0 assert client.remainder("B") == 1 with lock(url, "B"): assert client.remainder("A") == 0 assert client.remainder("B") == 0 assert client.remainder("A") == 0 assert client.remainder("B") == 1 assert client.remainder("A") == 1 assert client.remainder("B") == 1
def test_keep_lease_alive_beyond_expiration(): """ Validates that a heartbeat keeps the lease alive beyond the initial expiration time. """ with throttle(b"[semaphores]\nA=1") as url: client = Client(url) peer = PeerWithHeartbeat( client=client, heartbeat_interval=timedelta(seconds=1), expiration_time=timedelta(seconds=4), ) set_local_peer(url, peer) with lock(url, "A") as _: sleep(5) # Evens though enough time has passed, our lease should not be # expired, thanks to the heartbeat. assert client.remove_expired() == 0
def test_exception(): """ Assert that lock is freed in the presence of exceptions in the client code """ class OutOfCheese(Exception): pass checked = False with throttle(b"[semaphores]\nA=1") as url: client = Client(url) try: with lock(url, "A"): raise OutOfCheese() except OutOfCheese: assert client.remainder("A") == 1 checked = True # Make sure we entered exception handling assert checked
def acquire_lease_concurrent(client): with lock(BASE_URL, "A", timeout=timedelta(seconds=10)): nonlocal acquired_lease acquired_lease = True