def test_is_available_empty(self, mode): req = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode self.assertTrue(lock.isAvailable(req, access))
def test_count_cannot_be_larger_than_maxcount(self, count, maxCount): req = Requester() lock = BaseLock('test', maxCount=maxCount) access = mock.Mock(spec=LockAccess) access.mode = 'counting' access.count = count self.assertFalse(lock.isAvailable(req, access))
def test_exclusive_must_have_count_one(self, count, maxCount): req = Requester() lock = BaseLock('test', maxCount=maxCount) access = mock.Mock(spec=LockAccess) access.mode = 'exclusive' access.count = count with self.assertRaises(AssertionError): lock.claim(req, 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_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_can_release_non_waited_lock(self, mode): req = Requester() req_not_waited = Requester() lock = BaseLock('test', maxCount=1) access = mock.Mock(spec=LockAccess) access.mode = mode lock.release(req_not_waited, access) lock.claim(req, access) lock.release(req, access) yield flushEventualQueue() lock.release(req_not_waited, access)
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_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_is_available_without_waiter(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.release(req, access) self.assertTrue(lock.isAvailable(req, access)) self.assertTrue(lock.isAvailable(req_waiter, 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 getLock(self, worker): host_name = worker.worker_environ.get('WORKER_HOST', None) assert host_name is not None if host_name not in self.locks: max_count = self.max_count_for_host.get(host_name, self.max_count) lock = self.locks[host_name] = BaseLock(self.name, max_count) desc = "<HostLock(%s, %s)[%s] %d>" % (self.name, max_count, host_name, id(lock)) lock.description = desc self.locks[host_name] = lock return self.locks[host_name]
def test_different_counts_over_limit(self, count1, count2, maxCount): req1 = Requester() req2 = Requester() lock = BaseLock('test', maxCount=maxCount) access1 = mock.Mock(spec=LockAccess) access1.mode = 'counting' access1.count = count1 access2 = mock.Mock(spec=LockAccess) access2.mode = 'counting' access2.count = count2 self.assertTrue(lock.isAvailable(req1, access1)) lock.claim(req1, access1) self.assertFalse(lock.isAvailable(req2, access2)) lock.release(req1, access1)
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)
def test_release_calls_multiple_waiters_on_setMaxCount(self): req = Requester() req_waiters = [Requester() for _ in range(5)] lock = BaseLock('test', maxCount=1) access_counting = mock.Mock(spec=LockAccess) access_counting.mode = 'counting' 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_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_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_stop_waiting_does_not_raise_after_release(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) 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): 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_counting_count_zero_always_succeeds(self, count, maxCount): reqs = [Requester() for _ in range(10)] req_waiters = [Requester() for _ in range(10)] req_nonzero = Requester() lock = BaseLock('test', maxCount=maxCount) access_zero = mock.Mock(spec=LockAccess) access_zero.mode = 'counting' access_zero.count = 0 access_nonzero = mock.Mock(spec=LockAccess) access_nonzero.mode = 'counting' access_nonzero.count = count lock.claim(req_nonzero, access_nonzero) for req in reqs: self.assertTrue(lock.isAvailable(req, access_zero)) lock.claim(req, access_zero) for req_waiter in req_waiters: self.assertTrue(lock.isAvailable(req_waiter, access_zero)) for req in reqs: self.assertTrue(lock.isAvailable(req, access_zero)) lock.release(req, access_zero) lock.release(req_nonzero, access_nonzero)
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_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_is_available_with_mult_waiters_mult_counting_set_maxCount(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.setMaxCount(4) 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_waiter1, access) lock.release(req_waiter1, 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.setMaxCount(2) lock.waitUntilMaybeAvailable(req_waiter1, access) lock.claim(req_waiter2, access) lock.release(req_waiter2, access) self.assertFalse(lock.isAvailable(req1, access)) self.assertTrue(lock.isAvailable(req_waiter1, access)) self.assertFalse(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)) lock.claim(req_waiter1, access) lock.release(req_waiter1, access)