@Test public void testValidateConnectionStale() throws Exception { final HttpConnection conn = Mockito.mock(HttpConnection.class); Mockito.when(conn.isOpen()).thenReturn(true); Mockito.when(conn.isStale()).thenReturn(false); final LocalConnFactory connFactory = Mockito.mock(LocalConnFactory.class); Mockito.when(connFactory.create(Mockito.eq("somehost"))).thenReturn(conn); final LocalConnPool pool = new LocalConnPool(connFactory, 2, 10); pool.setValidateAfterInactivity(5); final Future<LocalPoolEntry> future1 = pool.lease("somehost", null); final LocalPoolEntry entry1 = future1.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry1); pool.release(entry1, true); Thread.sleep(10); Mockito.verify(connFactory, Mockito.times(1)).create("somehost"); Mockito.when(conn.isStale()).thenReturn(true); final Future<LocalPoolEntry> future2 = pool.lease("somehost", null); final LocalPoolEntry entry2 = future2.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry2); Assert.assertNotSame(entry1, entry2); Mockito.verify(conn, Mockito.times(1)).isStale(); Mockito.verify(conn, Mockito.times(1)).close(); Mockito.verify(connFactory, Mockito.times(2)).create("somehost"); }
@Test public void testLeaseCancel() throws Exception { final LocalConnFactory connFactory = Mockito.mock(LocalConnFactory.class); final HttpConnection conn1 = Mockito.mock(HttpConnection.class); Mockito.when(conn1.isOpen()).thenReturn(true); Mockito.when(connFactory.create(Mockito.eq("somehost"))).thenReturn(conn1); final LocalConnPool pool = new LocalConnPool(connFactory, 1, 1); final Future<LocalPoolEntry> future1 = pool.lease("somehost", null); final GetPoolEntryThread t1 = new GetPoolEntryThread(future1); t1.start(); t1.join(GRACE_PERIOD); Assert.assertTrue(future1.isDone()); final LocalPoolEntry entry1 = t1.getEntry(); Assert.assertNotNull(entry1); final Future<LocalPoolEntry> future2 = pool.lease("somehost", null); final GetPoolEntryThread t2 = new GetPoolEntryThread(future2); t2.start(); Thread.sleep(5); Assert.assertFalse(future2.isDone()); Assert.assertFalse(future2.isCancelled()); future2.cancel(true); t2.join(GRACE_PERIOD); Assert.assertTrue(future2.isDone()); Assert.assertTrue(future2.isCancelled()); future2.cancel(true); future2.cancel(true); }
@Test public void testCreateNewIfExpired() throws Exception { final LocalConnFactory connFactory = Mockito.mock(LocalConnFactory.class); final HttpConnection conn1 = Mockito.mock(HttpConnection.class); Mockito.when(conn1.isOpen()).thenReturn(true); Mockito.when(connFactory.create(Mockito.eq("somehost"))).thenReturn(conn1); final LocalConnPool pool = new LocalConnPool(connFactory, 2, 2); final Future<LocalPoolEntry> future1 = pool.lease("somehost", null); final LocalPoolEntry entry1 = future1.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry1); Mockito.verify(connFactory, Mockito.times(1)).create(Mockito.eq("somehost")); entry1.updateExpiry(1, TimeUnit.MILLISECONDS); pool.release(entry1, true); Thread.sleep(200L); final Future<LocalPoolEntry> future2 = pool.lease("somehost", null); final LocalPoolEntry entry2 = future2.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry2); Mockito.verify(connFactory, Mockito.times(2)).create(Mockito.eq("somehost")); final PoolStats totals = pool.getTotalStats(); Assert.assertEquals(0, totals.getAvailable()); Assert.assertEquals(1, totals.getLeased()); Assert.assertEquals(Collections.singleton("somehost"), pool.getRoutes()); final PoolStats stats = pool.getStats("somehost"); Assert.assertEquals(0, stats.getAvailable()); Assert.assertEquals(1, stats.getLeased()); }
@Test public void testShutdown() throws Exception { final LocalConnFactory connFactory = Mockito.mock(LocalConnFactory.class); final HttpConnection conn1 = Mockito.mock(HttpConnection.class); Mockito.when(conn1.isOpen()).thenReturn(true); Mockito.when(connFactory.create(Mockito.eq("somehost"))).thenReturn(conn1); final HttpConnection conn2 = Mockito.mock(HttpConnection.class); Mockito.when(conn2.isOpen()).thenReturn(true); Mockito.when(connFactory.create(Mockito.eq("otherhost"))).thenReturn(conn2); final LocalConnPool pool = new LocalConnPool(connFactory, 2, 2); final Future<LocalPoolEntry> future1 = pool.lease("somehost", null); final LocalPoolEntry entry1 = future1.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry1); final Future<LocalPoolEntry> future2 = pool.lease("otherhost", null); final LocalPoolEntry entry2 = future2.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry2); pool.release(entry2, true); final PoolStats totals = pool.getTotalStats(); Assert.assertEquals(1, totals.getAvailable()); Assert.assertEquals(1, totals.getLeased()); pool.shutdown(); Assert.assertTrue(pool.isShutdown()); pool.shutdown(); pool.shutdown(); Mockito.verify(conn1, Mockito.atLeastOnce()).close(); Mockito.verify(conn2, Mockito.atLeastOnce()).close(); try { pool.lease("somehost", null); Assert.fail("IllegalStateException should have been thrown"); } catch (final IllegalStateException expected) { } // Ignored if shut down pool.release(new LocalPoolEntry("somehost", Mockito.mock(HttpConnection.class)), true); }
@Test public void testCloseExpired() throws Exception { final LocalConnFactory connFactory = Mockito.mock(LocalConnFactory.class); final HttpConnection conn1 = Mockito.mock(HttpConnection.class); Mockito.when(conn1.isOpen()).thenReturn(Boolean.FALSE); final HttpConnection conn2 = Mockito.mock(HttpConnection.class); Mockito.when(conn2.isOpen()).thenReturn(Boolean.TRUE); Mockito.when(connFactory.create(Mockito.eq("somehost"))).thenReturn(conn1, conn2); final LocalConnPool pool = new LocalConnPool(connFactory, 2, 2); final Future<LocalPoolEntry> future1 = pool.lease("somehost", null); final LocalPoolEntry entry1 = future1.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry1); final Future<LocalPoolEntry> future2 = pool.lease("somehost", null); final LocalPoolEntry entry2 = future2.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry2); entry1.updateExpiry(1, TimeUnit.MILLISECONDS); pool.release(entry1, true); Thread.sleep(200); entry2.updateExpiry(1000, TimeUnit.SECONDS); pool.release(entry2, true); pool.closeExpired(); Mockito.verify(conn1).close(); Mockito.verify(conn2, Mockito.never()).close(); final PoolStats totals = pool.getTotalStats(); Assert.assertEquals(1, totals.getAvailable()); Assert.assertEquals(0, totals.getLeased()); final PoolStats stats = pool.getStats("somehost"); Assert.assertEquals(1, stats.getAvailable()); Assert.assertEquals(0, stats.getLeased()); }
@Test public void testLeaseRelease() throws Exception { final HttpConnection conn1 = Mockito.mock(HttpConnection.class); Mockito.when(conn1.isOpen()).thenReturn(true); final HttpConnection conn2 = Mockito.mock(HttpConnection.class); Mockito.when(conn2.isOpen()).thenReturn(true); final LocalConnFactory connFactory = Mockito.mock(LocalConnFactory.class); Mockito.when(connFactory.create(Mockito.eq("somehost"))).thenReturn(conn1); Mockito.when(connFactory.create(Mockito.eq("otherhost"))).thenReturn(conn2); final LocalConnPool pool = new LocalConnPool(connFactory, 2, 10); final Future<LocalPoolEntry> future1 = pool.lease("somehost", null); final LocalPoolEntry entry1 = future1.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry1); final Future<LocalPoolEntry> future2 = pool.lease("somehost", null); final LocalPoolEntry entry2 = future2.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry2); final Future<LocalPoolEntry> future3 = pool.lease("otherhost", null); final LocalPoolEntry entry3 = future3.get(1, TimeUnit.SECONDS); Assert.assertNotNull(entry3); PoolStats totals = pool.getTotalStats(); Assert.assertEquals(0, totals.getAvailable()); Assert.assertEquals(3, totals.getLeased()); final LocalPoolEntry entry = future1.get(); Assert.assertSame(entry1, entry); pool.release(entry1, true); pool.release(entry2, true); pool.release(entry3, false); Mockito.verify(conn1, Mockito.never()).close(); Mockito.verify(conn2, Mockito.times(1)).close(); totals = pool.getTotalStats(); Assert.assertEquals(2, totals.getAvailable()); Assert.assertEquals(0, totals.getLeased()); }
@Test public void testStatefulConnectionRedistributionOnPerRouteMaxLimit() throws Exception { final LocalConnFactory connFactory = Mockito.mock(LocalConnFactory.class); final HttpConnection conn1 = Mockito.mock(HttpConnection.class); Mockito.when(conn1.isOpen()).thenReturn(true); final HttpConnection conn2 = Mockito.mock(HttpConnection.class); Mockito.when(conn2.isOpen()).thenReturn(true); final HttpConnection conn3 = Mockito.mock(HttpConnection.class); Mockito.when(conn3.isOpen()).thenReturn(true); Mockito.when(connFactory.create(Mockito.eq("somehost"))).thenReturn(conn1, conn2, conn3); final LocalConnPool pool = new LocalConnPool(connFactory, 2, 10); pool.setMaxPerRoute("somehost", 2); pool.setMaxTotal(2); final Future<LocalPoolEntry> future1 = pool.lease("somehost", null); final GetPoolEntryThread t1 = new GetPoolEntryThread(future1); t1.start(); t1.join(GRACE_PERIOD); Assert.assertTrue(future1.isDone()); final LocalPoolEntry entry1 = t1.getEntry(); Assert.assertNotNull(entry1); final Future<LocalPoolEntry> future2 = pool.lease("somehost", null); final GetPoolEntryThread t2 = new GetPoolEntryThread(future2); t2.start(); t2.join(GRACE_PERIOD); Assert.assertTrue(future2.isDone()); final LocalPoolEntry entry2 = t2.getEntry(); Assert.assertNotNull(entry2); PoolStats totals = pool.getTotalStats(); Assert.assertEquals(0, totals.getAvailable()); Assert.assertEquals(2, totals.getLeased()); Assert.assertEquals(0, totals.getPending()); entry1.setState("some-stuff"); pool.release(entry1, true); entry2.setState("some-stuff"); pool.release(entry2, true); Mockito.verify(connFactory, Mockito.times(2)).create(Mockito.eq("somehost")); final Future<LocalPoolEntry> future3 = pool.lease("somehost", "some-other-stuff"); final GetPoolEntryThread t3 = new GetPoolEntryThread(future3); t3.start(); t3.join(GRACE_PERIOD); Assert.assertTrue(future3.isDone()); final LocalPoolEntry entry3 = t3.getEntry(); Assert.assertNotNull(entry3); Mockito.verify(connFactory, Mockito.times(3)).create(Mockito.eq("somehost")); Mockito.verify(conn1).close(); Mockito.verify(conn2, Mockito.never()).close(); totals = pool.getTotalStats(); Assert.assertEquals(1, totals.getAvailable()); Assert.assertEquals(1, totals.getLeased()); }
@Test public void testConnectionRedistributionOnTotalMaxLimit() throws Exception { final LocalConnFactory connFactory = Mockito.mock(LocalConnFactory.class); final HttpConnection conn1 = Mockito.mock(HttpConnection.class); Mockito.when(conn1.isOpen()).thenReturn(true); final HttpConnection conn2 = Mockito.mock(HttpConnection.class); Mockito.when(conn2.isOpen()).thenReturn(true); final HttpConnection conn3 = Mockito.mock(HttpConnection.class); Mockito.when(conn3.isOpen()).thenReturn(true); Mockito.when(connFactory.create(Mockito.eq("somehost"))).thenReturn(conn1, conn2, conn3); final HttpConnection conn4 = Mockito.mock(HttpConnection.class); Mockito.when(conn4.isOpen()).thenReturn(true); final HttpConnection conn5 = Mockito.mock(HttpConnection.class); Mockito.when(conn5.isOpen()).thenReturn(true); Mockito.when(connFactory.create(Mockito.eq("otherhost"))).thenReturn(conn4, conn5); final LocalConnPool pool = new LocalConnPool(connFactory, 2, 10); pool.setMaxPerRoute("somehost", 2); pool.setMaxPerRoute("otherhost", 2); pool.setMaxTotal(2); final Future<LocalPoolEntry> future1 = pool.lease("somehost", null); final GetPoolEntryThread t1 = new GetPoolEntryThread(future1); t1.start(); final Future<LocalPoolEntry> future2 = pool.lease("somehost", null); final GetPoolEntryThread t2 = new GetPoolEntryThread(future2); t2.start(); t1.join(GRACE_PERIOD); Assert.assertTrue(future1.isDone()); final LocalPoolEntry entry1 = t1.getEntry(); Assert.assertNotNull(entry1); t2.join(GRACE_PERIOD); Assert.assertTrue(future2.isDone()); final LocalPoolEntry entry2 = t2.getEntry(); Assert.assertNotNull(entry2); final Future<LocalPoolEntry> future3 = pool.lease("otherhost", null); final GetPoolEntryThread t3 = new GetPoolEntryThread(future3); t3.start(); final Future<LocalPoolEntry> future4 = pool.lease("otherhost", null); final GetPoolEntryThread t4 = new GetPoolEntryThread(future4); t4.start(); Assert.assertFalse(t3.isDone()); Assert.assertFalse(t4.isDone()); Mockito.verify(connFactory, Mockito.times(2)).create(Mockito.eq("somehost")); Mockito.verify(connFactory, Mockito.never()).create(Mockito.eq("otherhost")); PoolStats totals = pool.getTotalStats(); Assert.assertEquals(0, totals.getAvailable()); Assert.assertEquals(2, totals.getLeased()); pool.release(entry1, true); pool.release(entry2, true); t3.join(GRACE_PERIOD); Assert.assertTrue(future3.isDone()); final LocalPoolEntry entry3 = t3.getEntry(); Assert.assertNotNull(entry3); t4.join(GRACE_PERIOD); Assert.assertTrue(future4.isDone()); final LocalPoolEntry entry4 = t4.getEntry(); Assert.assertNotNull(entry4); Mockito.verify(connFactory, Mockito.times(2)).create(Mockito.eq("somehost")); Mockito.verify(connFactory, Mockito.times(2)).create(Mockito.eq("otherhost")); totals = pool.getTotalStats(); Assert.assertEquals(0, totals.getAvailable()); Assert.assertEquals(2, totals.getLeased()); final Future<LocalPoolEntry> future5 = pool.lease("somehost", null); final GetPoolEntryThread t5 = new GetPoolEntryThread(future5); t5.start(); final Future<LocalPoolEntry> future6 = pool.lease("otherhost", null); final GetPoolEntryThread t6 = new GetPoolEntryThread(future6); t6.start(); pool.release(entry3, true); pool.release(entry4, true); t5.join(GRACE_PERIOD); Assert.assertTrue(future5.isDone()); final LocalPoolEntry entry5 = t5.getEntry(); Assert.assertNotNull(entry5); t6.join(GRACE_PERIOD); Assert.assertTrue(future6.isDone()); final LocalPoolEntry entry6 = t6.getEntry(); Assert.assertNotNull(entry6); Mockito.verify(connFactory, Mockito.times(3)).create(Mockito.eq("somehost")); Mockito.verify(connFactory, Mockito.times(2)).create(Mockito.eq("otherhost")); totals = pool.getTotalStats(); Assert.assertEquals(0, totals.getAvailable()); Assert.assertEquals(2, totals.getLeased()); pool.release(entry5, true); pool.release(entry6, true); totals = pool.getTotalStats(); Assert.assertEquals(2, totals.getAvailable()); Assert.assertEquals(0, totals.getLeased()); }