def test_is_available_with_multiple_waiters(self, mode): req = Requester() req_waiter1 = Requester() req_waiter2 = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode lock.claim(req, access) lock.waitUntilMaybeAvailable(req_waiter1, access) lock.waitUntilMaybeAvailable(req_waiter2, access) lock.release(req, access) self.assertFalse(lock.isAvailable(req, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertFalse(lock.isAvailable(req_waiter2, access)) lock.claim(req_waiter1, access) lock.release(req_waiter1, access) self.assertFalse(lock.isAvailable(req, access)) self.assertFalse(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access)) lock.claim(req_waiter2, access) lock.release(req_waiter2, access) self.assertTrue(lock.isAvailable(req, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access))
def test_duplicate_wait_until_maybe_available_throws(self, mode): req = Requester() req_waiter = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode lock.claim(req, access) lock.waitUntilMaybeAvailable(req_waiter, access) with self.assertRaises(AssertionError): lock.waitUntilMaybeAvailable(req_waiter, access) lock.release(req, access)
def test_stop_waiting_removes_non_called_waiter(self, mode): req = Requester() req_waiter1 = Requester() req_waiter2 = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode lock.claim(req, access) d1 = lock.waitUntilMaybeAvailable(req_waiter1, access) d2 = lock.waitUntilMaybeAvailable(req_waiter2, access) lock.release(req, access) yield flushEventualQueue() self.assertFalse(lock.isAvailable(req, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertFalse(lock.isAvailable(req_waiter2, access)) self.assertTrue(d1.called) lock.stopWaitingUntilAvailable(req_waiter2, access, d2) self.assertFalse(lock.isAvailable(req, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertFalse(lock.isAvailable(req_waiter2, access)) lock.claim(req_waiter1, access) lock.release(req_waiter1, access) self.assertTrue(lock.isAvailable(req, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access))
def test_release_calls_multiple_waiters_on_setMaxCount( self, count, maxCount): req = Requester() req_waiters = [Requester() for _ in range(5)] lock = BaseLock('test', maxCount=maxCount) access_counting = mock.Mock(spec=LockAccess) access_counting.mode = 'counting' access_counting.count = count lock.claim(req, access_counting) deferreds = [ lock.waitUntilMaybeAvailable(req_waiter, access_counting) for req_waiter in req_waiters ] self.assertEqual([d.called for d in deferreds], [False] * 5) lock.release(req, access_counting) yield flushEventualQueue() self.assertEqual([d.called for d in deferreds], [True] + [False] * 4) lock.setMaxCount(5) yield flushEventualQueue() self.assertEqual([d.called for d in deferreds], [True] * 5)
def test_stop_waiting_ensures_deferred_was_previous_result_of_wait(self, mode): req = Requester() req_waiter = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode lock.claim(req, access) lock.waitUntilMaybeAvailable(req_waiter, access) with self.assertRaises(AssertionError): wrong_d = defer.Deferred() lock.stopWaitingUntilAvailable(req_waiter, access, wrong_d) lock.release(req, access)
def test_is_available_with_multiple_waiters_multiple_counting(self): req1 = Requester() req2 = Requester() req_waiter1 = Requester() req_waiter2 = Requester() req_waiter3 = Requester() lock = BaseLock('test', maxCount=2) access = mock.Mock(spec=LockAccess) access.mode = 'counting' access.count = 1 lock.claim(req1, access) lock.claim(req2, access) lock.waitUntilMaybeAvailable(req_waiter1, access) lock.waitUntilMaybeAvailable(req_waiter2, access) lock.waitUntilMaybeAvailable(req_waiter3, access) lock.release(req1, access) lock.release(req2, access) self.assertFalse(lock.isAvailable(req1, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access)) self.assertFalse(lock.isAvailable(req_waiter3, access)) lock.claim(req_waiter1, access) lock.release(req_waiter1, access) self.assertFalse(lock.isAvailable(req1, access)) self.assertFalse(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access)) self.assertTrue(lock.isAvailable(req_waiter3, access)) lock.claim(req_waiter2, access) lock.release(req_waiter2, access) self.assertTrue(lock.isAvailable(req1, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access)) self.assertTrue(lock.isAvailable(req_waiter3, access)) lock.claim(req_waiter3, access) lock.release(req_waiter3, access) self.assertTrue(lock.isAvailable(req1, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access)) self.assertTrue(lock.isAvailable(req_waiter3, access))
def test_is_available_with_multiple_waiters_multiple_counting(self): req1 = Requester() req2 = Requester() req_waiter1 = Requester() req_waiter2 = Requester() req_waiter3 = Requester() lock = BaseLock('test', maxCount=2) access = mock.Mock(spec=LockAccess) access.mode = 'counting' lock.claim(req1, access) lock.claim(req2, access) lock.waitUntilMaybeAvailable(req_waiter1, access) lock.waitUntilMaybeAvailable(req_waiter2, access) lock.waitUntilMaybeAvailable(req_waiter3, access) lock.release(req1, access) lock.release(req2, access) self.assertFalse(lock.isAvailable(req1, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access)) self.assertFalse(lock.isAvailable(req_waiter3, access)) lock.claim(req_waiter1, access) lock.release(req_waiter1, access) self.assertFalse(lock.isAvailable(req1, access)) self.assertFalse(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access)) self.assertTrue(lock.isAvailable(req_waiter3, access)) lock.claim(req_waiter2, access) lock.release(req_waiter2, access) self.assertTrue(lock.isAvailable(req1, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access)) self.assertTrue(lock.isAvailable(req_waiter3, access)) lock.claim(req_waiter3, access) lock.release(req_waiter3, access) self.assertTrue(lock.isAvailable(req1, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertTrue(lock.isAvailable(req_waiter2, access)) self.assertTrue(lock.isAvailable(req_waiter3, access))
def test_is_available_with_waiter(self, mode, count, maxCount): req = Requester() req_waiter = Requester() lock = BaseLock('test', maxCount=maxCount) access = mock.Mock(spec=LockAccess) access.mode = mode access.count = count lock.claim(req, access) lock.waitUntilMaybeAvailable(req_waiter, access) lock.release(req, access) self.assertFalse(lock.isAvailable(req, access)) self.assertTrue(lock.isAvailable(req_waiter, access)) lock.claim(req_waiter, access) lock.release(req_waiter, access) self.assertTrue(lock.isAvailable(req, access)) self.assertTrue(lock.isAvailable(req_waiter, access))
def test_stop_waiting_fires_deferred_if_not_woken(self, mode): req = Requester() req_waiter = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode lock.claim(req, access) d = lock.waitUntilMaybeAvailable(req_waiter, access) lock.stopWaitingUntilAvailable(req_waiter, access, d) self.assertTrue(d.called) lock.release(req, access)
def test_stop_waiting_does_not_fire_deferred_if_already_woken(self, mode): req = Requester() req_waiter = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode lock.claim(req, access) d = lock.waitUntilMaybeAvailable(req_waiter, access) lock.release(req, access) yield flushEventualQueue() self.assertTrue(d.called) # note that if the function calls the deferred again, an exception would be thrown from # inside Twisted. lock.stopWaitingUntilAvailable(req_waiter, access, d)
def test_stop_waiting_does_not_raise_after_release(self, mode): req = Requester() req_waiter = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode lock.claim(req, access) d = lock.waitUntilMaybeAvailable(req_waiter, access) lock.release(req, access) self.assertFalse(lock.isAvailable(req, access)) self.assertTrue(lock.isAvailable(req_waiter, access)) lock.stopWaitingUntilAvailable(req_waiter, access, d) lock.claim(req_waiter, access) lock.release(req_waiter, access)
def test_release_calls_waiters_in_fifo_order(self, mode1, mode2, count1, count2, maxCount): req = Requester() req_waiters = [Requester() for _ in range(5)] lock = BaseLock('test', maxCount=maxCount) access1 = mock.Mock(spec=LockAccess) access1.mode = mode1 access1.count = count1 access2 = mock.Mock(spec=LockAccess) access2.mode = mode2 access2.count = count2 accesses = [access1, access2, access1, access2, access1] expected_called = [False] * 5 lock.claim(req, access1) deferreds = [ lock.waitUntilMaybeAvailable(req_waiter, access) for req_waiter, access in zip(req_waiters, accesses) ] self.assertEqual([d.called for d in deferreds], expected_called) lock.release(req, access1) yield flushEventualQueue() expected_called[0] = True self.assertEqual([d.called for d in deferreds], expected_called) for i in range(4): self.assertTrue(lock.isAvailable(req_waiters[i], accesses[i])) lock.claim(req_waiters[i], accesses[i]) self.assertEqual([d.called for d in deferreds], expected_called) lock.release(req_waiters[i], accesses[i]) yield flushEventualQueue() expected_called[i + 1] = True self.assertEqual([d.called for d in deferreds], expected_called) lock.claim(req_waiters[4], accesses[4]) lock.release(req_waiters[4], accesses[4])
def test_stop_waiting_raises_after_release(self, mode): req = Requester() req_waiter = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode lock.claim(req, access) d = lock.waitUntilMaybeAvailable(req_waiter, access) lock.release(req, access) self.assertFalse(lock.isAvailable(req, access)) self.assertTrue(lock.isAvailable(req_waiter, access)) with self.assertRaises(AssertionError): lock.stopWaitingUntilAvailable(req_waiter, access, d) lock.claim(req_waiter, access) lock.release(req_waiter, access)
def test_release_calls_multiple_waiters_on_release(self): req = Requester() req_waiters = [Requester() for _ in range(5)] lock = BaseLock('test', maxCount=5) access_counting = mock.Mock(spec=LockAccess) access_counting.mode = 'counting' access_excl = mock.Mock(spec=LockAccess) access_excl.mode = 'exclusive' lock.claim(req, access_excl) deferreds = [lock.waitUntilMaybeAvailable(req_waiter, access_counting) for req_waiter in req_waiters] self.assertEqual([d.called for d in deferreds], [False] * 5) lock.release(req, access_excl) yield flushEventualQueue() self.assertEqual([d.called for d in deferreds], [True] * 5)
def test_release_calls_waiters_in_fifo_order(self, mode1, mode2): req = Requester() req_waiters = [Requester() for _ in range(5)] lock = BaseLock('test', maxCount=1) access1 = mock.Mock(spec=LockAccess) access1.mode = mode1 access2 = mock.Mock(spec=LockAccess) access2.mode = mode2 accesses = [access1, access2, access1, access2, access1] expected_called = [False] * 5 lock.claim(req, access1) deferreds = [lock.waitUntilMaybeAvailable(req_waiter, access) for req_waiter, access in zip(req_waiters, accesses)] self.assertEqual([d.called for d in deferreds], expected_called) lock.release(req, access1) yield flushEventualQueue() expected_called[0] = True self.assertEqual([d.called for d in deferreds], expected_called) for i in range(4): self.assertTrue(lock.isAvailable(req_waiters[i], accesses[i])) lock.claim(req_waiters[i], accesses[i]) self.assertEqual([d.called for d in deferreds], expected_called) lock.release(req_waiters[i], accesses[i]) yield flushEventualQueue() expected_called[i + 1] = True self.assertEqual([d.called for d in deferreds], expected_called) lock.claim(req_waiters[4], accesses[4]) lock.release(req_waiters[4], accesses[4])
def test_stop_waiting_wakes_up_next_deferred_if_already_woken(self, mode): req = Requester() req_waiter1 = Requester() req_waiter2 = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode lock.claim(req, access) d1 = lock.waitUntilMaybeAvailable(req_waiter1, access) d2 = lock.waitUntilMaybeAvailable(req_waiter2, access) lock.release(req, access) yield flushEventualQueue() self.assertTrue(d1.called) self.assertFalse(d2.called) lock.stopWaitingUntilAvailable(req_waiter1, access, d1) yield flushEventualQueue() self.assertTrue(d2.called)