@Test public void testDiscardExpiredConnections() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(2, 1, connector); FakeWaiter waiter1 = new FakeWaiter(); mgr.getConnection(waiter1); FakeConnection conn = connector.assertRequest(); conn.connect(); assertWaitUntil(waiter1::isSuccess); conn.recycle(2L); assertEquals(1, mgr.size()); assertEquals(0, mgr.removeExpired(1L)); assertEquals(1, mgr.size()); assertEquals(1, mgr.removeExpired(2L)); assertEquals(0, mgr.size()); }
@Test public void testConnectPoolEmptyWaiterCancelledAfterConnectRequest() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(3, 3, connector); FakeWaiter waiter = new FakeWaiter(); mgr.getConnection(waiter); FakeConnection conn = connector.assertRequest(); waiter.cancel(); conn.connect(); assertWaitUntil(waiter::isComplete); assertFalse(waiter.isSuccess()); assertFalse(waiter.isFailure()); assertFalse(mgr.contains(conn)); }
@Test public void testSynchronousConnectionFailure() { Throwable cause = new Throwable(); ConnectionProvider<FakeConnection> connector = new FakeConnectionProviderBase() { @Override public void connect(ConnectionListener<FakeConnection> listener, ContextInternal context, Handler<AsyncResult<ConnectResult<FakeConnection>>> handler) { handler.handle(Future.failedFuture(cause)); } }; FakeConnectionManager mgr = new FakeConnectionManager(3, 3, connector); for (int i = 0;i < 4;i++) { FakeWaiter waiter = new FakeWaiter(); mgr.getConnection(waiter); waitUntil(waiter::isFailure); waiter.assertFailure(cause); assertEquals(0, mgr.pool().weight()); } assertTrue(mgr.closed()); }
@Test public void testConnectionFailure() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(3, 3, connector); FakeWaiter waiter = new FakeWaiter(); mgr.getConnection(waiter); FakeConnection conn = connector.assertRequest(); Exception expected = new Exception(); conn.fail(expected); assertWaitUntil(waiter::isComplete); waiter.assertFailure(expected); assertTrue(waiter.isFailure()); assertWaitUntil(mgr::closed); }
@Test public void testInitialNoConcurrency() { int n = 10; FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(-1, 1, connector); List<FakeWaiter> waiters = new ArrayList<>(); for (int i = 0; i < n; i++) { FakeWaiter waiter = new FakeWaiter(); mgr.getConnection(waiter); waiters.add(waiter); } FakeConnection conn = connector.assertRequest(); conn.concurrency(0).connect().awaitConnected(); conn.concurrency(n - 1); assertWaitUntil(() -> waiters.stream().filter(FakeWaiter::isSuccess).count() == n - 1); waiters.stream().filter(FakeWaiter::isSuccess).findFirst().get().recycle(); waiters.forEach(waiter -> { assertWaitUntil(waiter::isSuccess); }); }
@Test public void testQueueMaxSize() { checkQueueMaxSize(2, 3); checkQueueMaxSize(0, 3); }
@Test public void testInitialConcurrency() { int n = 10; FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(-1, 1, connector); List<FakeWaiter> waiters = new ArrayList<>(); for (int i = 0; i < n; i++) { FakeWaiter waiter = new FakeWaiter(); mgr.getConnection(waiter); waiters.add(waiter); } FakeConnection conn = connector.assertRequest(); conn.concurrency(n).connect(); waiters.forEach(waiter -> { assertWaitUntil(waiter::isSuccess); }); waiters.forEach(FakeWaiter::recycle); }
@Test public void testConnectionFailure() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(3, 3, connector); FakeWaiter waiter = new FakeWaiter(); mgr.getConnection(waiter); FakeConnection conn = connector.assertRequest(); Exception expected = new Exception(); conn.fail(expected); assertWaitUntil(waiter::isComplete); waiter.assertFailure(expected); assertTrue(waiter.isFailure()); assertWaitUntil(mgr::closed); }
@Test public void testQueueMaxSize() { checkQueueMaxSize(2, 3); checkQueueMaxSize(0, 3); }
assertWaitUntil(() -> mgr.closed()); assertEquals(1, mgr.closeCount()); assertEquals(0, mgr.size()); assertEquals(0, mgr.pool.waitersInQueue()); assertEquals(0, mgr.pool.weight()); assertEquals(0, mgr.pool.capacity());
private void checkQueueMaxSize(int queueMaxSize, int poolMaxSize) { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(queueMaxSize, poolMaxSize, connector); FakeWaiter[] waiters = new FakeWaiter[poolMaxSize + queueMaxSize]; for (int i = 0;i < poolMaxSize + queueMaxSize;i++) { FakeWaiter waiter = new FakeWaiter(); waiters[i] = waiter; mgr.getConnection(waiter); } FakeWaiter waiter = new FakeWaiter(); mgr.getConnection(waiter); assertWaitUntil(waiter::isFailure); for (int i = 0;i < poolMaxSize + queueMaxSize;i++) { assertFalse("Was not expecting connection no=" + i + " to be failed", waiters[i].isFailure()); } }
@Test public void testSynchronousConnectionFailure() { Throwable cause = new Throwable(); ConnectionProvider<FakeConnection> connector = new FakeConnectionProviderBase() { @Override public void connect(ConnectionListener<FakeConnection> listener, ContextInternal context, Handler<AsyncResult<ConnectResult<FakeConnection>>> handler) { handler.handle(Future.failedFuture(cause)); } }; FakeConnectionManager mgr = new FakeConnectionManager(3, 3, connector); for (int i = 0;i < 4;i++) { FakeWaiter waiter = new FakeWaiter(); mgr.getConnection(waiter); waitUntil(waiter::isFailure); waiter.assertFailure(cause); assertEquals(0, mgr.pool().weight()); } assertTrue(mgr.closed()); }
@Test public void testRecycleConnection() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(3, 1, connector); FakeWaiter waiter1 = new FakeWaiter(); mgr.getConnection(waiter1); FakeConnection conn = connector.assertRequest(); conn.connect(); assertWaitUntil(waiter1::isComplete); FakeWaiter waiter2 = new FakeWaiter(); mgr.getConnection(waiter2); connector.assertRequests(0); waiter1.recycle(); assertWaitUntil(waiter2::isComplete); waiter2.assertSuccess(conn); }
@Test public void testConnectSuccess() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(3, 4, connector); AtomicReference<Boolean> handleLock = new AtomicReference<>(); FakeWaiter waiter = new FakeWaiter() { @Override public synchronized void handleConnection(FakeConnection conn) { assertSame(conn.context, mgr.context); Pool<FakeConnection> pool = mgr.pool(); handleLock.set(Thread.holdsLock(pool)); super.handleConnection(conn); } }; mgr.getConnection(waiter); FakeConnection conn = connector.assertRequest(); conn.connect(); assertWaitUntil(waiter::isComplete); assertEquals(Boolean.FALSE, handleLock.get()); waiter.assertSuccess(conn); waiter.recycle(); assertEquals(0, mgr.size()); assertWaitUntil(() -> mgr.closed()); }
@Test public void testDontCloseEndpointWithInflightRequest() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(3, 2, connector); FakeWaiter waiter1 = new FakeWaiter(); mgr.getConnection(waiter1); FakeConnection conn = connector.assertRequest(); conn.connect(); assertWaitUntil(waiter1::isComplete); FakeWaiter waiter2 = new FakeWaiter(); mgr.getConnection(waiter2); conn.close(); assertWaitUntil(() -> !mgr.contains(conn)); assertFalse(mgr.closed()); }
@Test public void testDiscardWaiterWhenFull() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(2, 1, connector); FakeWaiter waiter1 = new FakeWaiter(); mgr.getConnection(waiter1); FakeConnection conn = connector.assertRequest(); FakeWaiter waiter2 = new FakeWaiter(); mgr.getConnection(waiter2); FakeWaiter waiter3 = new FakeWaiter(); mgr.getConnection(waiter3); FakeWaiter waiter4 = new FakeWaiter(); mgr.getConnection(waiter4); assertWaitUntil(waiter4::isFailure); // Full }
@Test public void testConnectFailure() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(3, 4, connector); AtomicReference<Boolean> holdsLock = new AtomicReference<>(); FakeWaiter waiter = new FakeWaiter() { @Override public synchronized void handleFailure(Throwable failure) { assertNull(Vertx.currentContext()); Pool<FakeConnection> pool = mgr.pool(); holdsLock.set(Thread.holdsLock(pool)); super.handleFailure(failure); } }; mgr.getConnection(waiter); FakeConnection conn = connector.assertRequest(); Throwable failure = new Throwable(); conn.fail(failure); assertWaitUntil(waiter::isComplete); assertEquals(Boolean.FALSE, holdsLock.get()); waiter.assertFailure(failure); }
@Test public void testRecycleDiscardedConnection() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(3, 1, connector); FakeWaiter waiter1 = new FakeWaiter(); mgr.getConnection(waiter1); FakeConnection conn = connector.assertRequest(); conn.connect(); assertWaitUntil(waiter1::isComplete); FakeWaiter waiter2 = new FakeWaiter(); mgr.getConnection(waiter2); conn.close(); waiter1.recycle(); assertWaitUntil(() -> connector.requests() == 1); assertFalse(mgr.closed()); FakeConnection conn2 = connector.assertRequest(); conn2.connect(); assertWaitUntil(waiter2::isSuccess); }
@Test public void testCloseRecycledConnection() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(2, 1, connector); FakeWaiter waiter1 = new FakeWaiter(); mgr.getConnection(waiter1); FakeConnection conn = connector.assertRequest(); conn.connect(); assertWaitUntil(waiter1::isSuccess); conn.recycle(2L); FakeWaiter waiter2 = new FakeWaiter(); // Recycle connection mgr.getConnection(waiter2); // But close it conn.close(); // We have a race here if (waiter2.isComplete()) { // Either the waiter acquires the recycled connection before it's closed } else { // Or a connection request happens conn = connector.assertRequest(); } }
@Test public void testEndpointLifecycle() { FakeConnectionProvider connector = new FakeConnectionProvider(); FakeConnectionManager mgr = new FakeConnectionManager(3, 1, connector); FakeWaiter waiter1 = new FakeWaiter(); mgr.getConnection(waiter1); FakeConnection conn = connector.assertRequest(); conn.connect(); assertWaitUntil(waiter1::isSuccess); conn.close(); assertWaitUntil(mgr::closed); FakeWaiter waiter2 = new FakeWaiter(); mgr.getConnection(waiter2); assertEquals(2, mgr.sequence()); }