def test_minmax_size() -> None: """Check that resources are destroyed when the pool overflows. Given: - a resource pool initialized with a min and a max poolsize and a dealloc function When: - more resources than the max poolsize are acquired - and the resources are all put back into the pool Then: - the surplus resources will be reset using the dealloc function """ pool = ResourcePool(alloc=R, dealloc=R.close, minsize=1, maxsize=2) a, b, c = pool.pop(), pool.pop(), pool.pop() pool.push(a) pool.push(b) pool.push(c) sleep(1) # wait for pool's gc thread assert len(R.deallocated) == 2 assert a in R.deallocated assert not a.alive assert b in R.deallocated assert not b.alive assert c.alive
def test_maxage() -> None: """Test maxage parameter.""" size = 5 pool = ResourcePool(alloc=now, maxage=1) resources = [pool.pop() for _ in range(size)] for r in resources: pool.push(r) assert len(pool) == size sleep(1.1) assert len(pool) == 0
def test_provide_additional_resource() -> None: """Resources are actually reused after returning.""" allocate = MagicMock() allocate.side_effect = R.create(4) pool = ResourcePool(alloc=allocate) resources = [pool.pop() for _ in range(3)] R.set(100) pool.push(R()) resources.append(pool.pop()) resources.append(pool.pop()) allocate.assert_has_calls([call(), call(), call(), call()]) assert resources == [0, 1, 2, 100, 3]
def test_no_resources_eternal_timeout() -> None: """Test behaviour with an infinite timeout when there are no resources available. Given: - a default-initialized resource pool - there are no resources currently available in the pool - and the pool has no way of creating a new resource (i. e., `alloc` was not given on construction) When: - client code attempts to get a resurce with an infinite timeout (=0) Then: - no exception will be raised - the `pop` method will block until a resource is made available by another thread """ pool = ResourcePool() timeout = 1 threading.Timer(timeout, lambda: pool.push(R())).start() start = now() with pool(timeout=0) as r: assert r == 0 duration = now() - start assert duration == pytest.approx(timeout, abs=1e-2)
def test_maxage_minsize() -> None: """Test maxage parameter with minimum size.""" size = 5 pool = ResourcePool(alloc=now, maxage=1, minsize=1) resources = [pool.pop() for _ in range(size)] assert len(pool) == 0 for r in resources: sleep(0.1) pool.push(r) assert len(pool) == size sleep(2) assert len(pool) == 1 expected = max(resources) actual = pool.pop() assert actual == expected
def test_max_size_no_overflow() -> None: """Check that resources are not destroyed unless the pool overflows. Given: - a resource pool initialized with a max poolsize and a dealloc function When: - the maxsize amount of resources are allocated - and the resources are all put back into the pool Then: - no resources will be reset using the dealloc function """ pool = ResourcePool(alloc=R, dealloc=R.close, minsize=0, maxsize=2) a, b = pool.pop(), pool.pop() pool.push(a) pool.push(b) sleep(1) # wait for pool's gc thread assert len(R.deallocated) == 0 assert a.alive assert b.alive
def test_reuse() -> None: """Resources are actually reused after returning.""" allocate = MagicMock() allocate.side_effect = [1, 2, 3, 4] pool = ResourcePool(alloc=allocate) resources = [] for _ in range(3): with pool() as r: resources.append(r) pool.push(100) resources.append(pool.pop()) for _ in range(2): with pool() as r: resources.append(r) allocate.assert_called_once() assert resources == [1, 1, 1, 100, 1, 1]