def test_object_pool_count(): def count(pool): counts = (pool.count(), pool.count_free(), pool.count_busy()) return 'total=%d free=%d busy=%d' % counts pool = lets.ObjectPool(2, object) assert count(pool) == 'total=0 free=0 busy=0' a = pool.get(block=False) assert count(pool) == 'total=1 free=0 busy=1' b = pool.get(block=False) assert count(pool) == 'total=2 free=0 busy=2' with pytest.raises(gevent.Timeout): pool.get(block=False) assert count(pool) == 'total=2 free=0 busy=2' pool.release(a) assert count(pool) == 'total=2 free=1 busy=1' pool.release(a) # again assert count(pool) == 'total=2 free=1 busy=1' pool.release(b) assert count(pool) == 'total=2 free=2 busy=0' pool.discard(a) assert count(pool) == 'total=1 free=1 busy=0' b2 = pool.get(block=False) assert b2 is b assert count(pool) == 'total=1 free=0 busy=1' pool.discard(b2) assert count(pool) == 'total=0 free=0 busy=0' sink_pool = lets.ObjectPool(1, object, discard_later=0.1) assert count(sink_pool) == 'total=0 free=0 busy=0' c = sink_pool.get(block=False) assert count(sink_pool) == 'total=1 free=0 busy=1' sink_pool.release(c) assert count(sink_pool) == 'total=1 free=1 busy=0' gevent.sleep(0.2) assert count(sink_pool) == 'total=0 free=0 busy=0'
def test_object_pool_discard_immediately(): pool = lets.ObjectPool(None, object, discard_later=0) assert pool.count() == 0 x = pool.get() assert pool.count() == 1 pool.release(x) assert pool.count() == 0
def test_object_pool_clear(): events = [] pool = lets.ObjectPool(2, lambda: events.pop(), lambda e: e.set()) # clear all _events = [Event(), Event()] events.extend(_events) with pool.reserve(): with pool.reserve(): pass assert pool.count() == 2 assert [e.is_set() for e in _events] == [False, False] pool.clear() assert pool.count() == 0 assert [e.is_set() for e in _events] == [True, True] # clear only available _events = [Event(), Event()] events.extend(_events) with pool.reserve(): with pool.reserve(): pass assert pool.count() == 2 assert [e.is_set() for e in _events] == [False, False] pool.clear() assert pool.count() == 1 assert [e.is_set() for e in _events] == [True, False] pool.clear() assert [e.is_set() for e in _events] == [True, False] pool.clear() assert pool.count() == 0 assert [e.is_set() for e in _events] == [True, True]
def test_object_pool_context(): pool = lets.ObjectPool(1, object) assert pool.available() with pool.reserve() as o: assert type(o) is object assert not pool.available() assert pool.available()
def test_object_pool(): # getting object blocks pool = lets.ObjectPool(2, object) assert pool.available() assert pool.count() == 0 o1 = pool.get() assert pool.available() assert pool.count() == 1 o2 = pool.get() assert not pool.available() with pytest.raises(gevent.Timeout): pool.get(timeout=0.1) assert o1 is not o2 assert pool.count() == 2 # release and get again pool.release(o1) assert pool.available() o3 = pool.get() assert not pool.available() assert o1 is o3 assert pool.count() == 2 # discard pool.discard(o2) o4 = pool.get() assert not pool.available() assert o2 is not o4 pool.discard(o4) assert pool.available()
def test_object_pool_wait_available(): pool = lets.ObjectPool(1, object) o = pool.get() waiting_avaiable = gevent.spawn(pool.wait_available) waiting_avaiable.join(0.1) assert not waiting_avaiable.ready() pool.release(o) waiting_avaiable.join(0.1) assert waiting_avaiable.ready()
def test_object_pool_with_slow_behaviors(): def slow(): gevent.sleep(0.1) return object() pool = lets.ObjectPool(2, slow) def consume_obj_from_pool(): with pool.reserve(): gevent.sleep(0.1) gevent.joinall([gevent.spawn(consume_obj_from_pool) for x in range(10)]) assert pool.count() == 2
def test_object_pool_deadlock(): zero_div = lambda: 0 / 0 pool = lets.ObjectPool(1, zero_div) with pytest.raises(ZeroDivisionError): pool.get() with pytest.raises(ZeroDivisionError): with gevent.Timeout(1, AssertionError('deadlock detected')): pool.get()
def test_object_pool_as_just_factory(): objects = set() def factory(): obj = object() objects.add(obj) return obj def destroy(obj): objects.remove(obj) # Actually, ObjectPool with (size=None, discard_later=0) is not useful as # a pool. get() always succeeds, release() always destroys the object. # The pool just looks like an object factory. pool = lets.ObjectPool(None, factory, destroy, discard_later=0) with pool.reserve() as a: assert a in objects with pool.reserve() as b: assert a in objects assert b in objects assert a is not b with pool.reserve() as c: assert a in objects assert b in objects assert c in objects assert a is not b assert a is not c assert b is not c assert a in objects assert b in objects assert c not in objects assert a in objects assert b not in objects assert c not in objects assert a not in objects assert b not in objects assert c not in objects
def test_object_pool_rotation(): counter = [0] def f(): counter[0] += 1 return counter[0] pool = lets.ObjectPool(3, f) assert pool.get() == 1 assert pool.get() == 2 assert pool.get() == 3 pool.release(1) pool.release(2) pool.release(3) assert pool.get() == 1 pool.discard(2) assert pool.get() == 3 assert pool.get() == 4 pool.discard(1) pool.release(1) assert pool.get() == 5 assert not pool.available()
def test_object_pool_discard_later(): pool = lets.ObjectPool(1, object, discard_later=0.1) with pool.reserve() as a: pass with pool.reserve() as b: pass assert a is b assert pool.count() == 1 gevent.sleep(0.2) assert pool.count() == 0 with pool.reserve() as c: pass assert a is not c gevent.sleep(0.05) # try to discard soon with pool.reserve() as d: gevent.sleep(0.2) # but busy assert c is d
def test_object_pool_discard_later_cancel_when_get(count_greenlets): def slow_destroy(obj): gevent.sleep(1) pool = lets.ObjectPool(1, object, slow_destroy, discard_later=0.1) assert count_greenlets() == 0 with pool.reserve() as a: pass # reserve discard() in 0.1 sec assert count_greenlets() == 1 with pool.reserve() as b: # reserved discard() is canceled assert count_greenlets() == 0 assert a is b # reserve discard() in 0.1 sec again assert count_greenlets() == 1
def test_object_pool_zero_size(): objects = set() def factory(): obj = object() objects.add(obj) return obj def destroy(obj): objects.remove(obj) pool = lets.ObjectPool(None, factory, destroy, discard_later=0) with pool.reserve() as a: assert a in objects with pool.reserve() as b: assert a in objects assert b in objects assert a is not b with pool.reserve() as c: assert a in objects assert b in objects assert c in objects assert a is not b assert a is not c assert b is not c assert a in objects assert b in objects assert c not in objects assert a in objects assert b not in objects assert c not in objects assert a not in objects assert b not in objects assert c not in objects
def test_object_pool_unlimited(): # getting object blocks pool = lets.ObjectPool(None, object) assert pool.available() o1 = pool.get() assert pool.available() o2 = pool.get() assert pool.available() assert o1 is not o2 assert pool.count() == 2 # release and get again pool.release(o1) o3 = pool.get() assert o1 is o3 o4 = pool.get() assert o4 is not o1 assert o4 is not o2 assert pool.count() == 3 # discard pool.discard(o2) o5 = pool.get() assert o2 is not o5
def test_object_pool_discard_later_with_slow_destroy(): destroy_started = Event() destroy_ended = Event() def slow_destroy(obj): destroy_started.set() gevent.sleep(10) destroy_ended.set() pool = lets.ObjectPool(1, object, slow_destroy, discard_later=0.1) with pool.reserve() as a: pass destroy_started.wait() assert destroy_started.is_set() with pool.reserve() as b: pass # 'a' is still being destroyed. assert not destroy_ended.is_set() # 'b' should not be destroying 'a'. assert a is not b
def test_object_pool_discard_later_with_destroy(): objects = set() def factory(): obj = object() objects.add(obj) return obj def destroy(obj): objects.remove(obj) pool = lets.ObjectPool(1, factory, destroy, discard_later=0.1) with pool.reserve() as a: pass with pool.reserve() as b: pass assert a is b assert a in objects assert pool.count() == 1 gevent.sleep(0.2) assert pool.count() == 0 assert a not in objects with pool.reserve() as c: pass assert a is not c assert a not in objects assert c in objects gevent.sleep(0.05) # try to discard soon with pool.reserve() as d: gevent.sleep(0.2) # but busy assert c is d assert c in objects assert len(objects) == 1