You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2011/05/04 21:02:56 UTC

svn commit: r1099559 [2/2] - in /httpcomponents/httpasyncclient/trunk/httpasyncclient/src: main/java/org/apache/http/impl/nio/pool/ test/java/org/apache/http/impl/nio/concurrent/ test/java/org/apache/http/impl/nio/pool/

Added: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/pool/TestSessionPool.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/pool/TestSessionPool.java?rev=1099559&view=auto
==============================================================================
--- httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/pool/TestSessionPool.java (added)
+++ httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/pool/TestSessionPool.java Wed May  4 19:02:55 2011
@@ -0,0 +1,869 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.http.impl.nio.pool;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketTimeoutException;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
+
+import org.apache.http.nio.conn.PoolStats;
+import org.apache.http.nio.reactor.ConnectingIOReactor;
+import org.apache.http.nio.reactor.IOSession;
+import org.apache.http.nio.reactor.SessionRequest;
+import org.apache.http.nio.reactor.SessionRequestCallback;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TestSessionPool {
+
+    static class LocalPoolEntry extends PoolEntry<String> {
+
+        public LocalPoolEntry(final String route, final IOSession iosession,
+                long timeToLive, final TimeUnit tunit) {
+            super(route, iosession, timeToLive, tunit);
+        }
+
+    }
+
+    static class LocalPoolEntryFactory implements PoolEntryFactory<String, PoolEntry<String>> {
+
+        public PoolEntry<String> createEntry(final String route, final IOSession session) {
+            return new LocalPoolEntry(route, session, 0L, TimeUnit.MILLISECONDS);
+        }
+
+    };
+
+    static class LocalRouteResolver implements RouteResolver<String> {
+
+        public SocketAddress resolveRemoteAddress(final String route) {
+            return InetSocketAddress.createUnresolved(route, 80);
+        }
+
+        public SocketAddress resolveLocalAddress(final String route) {
+            return InetSocketAddress.createUnresolved(route, 80);
+        }
+
+    };
+
+    static class LocalSessionPool extends SessionPool<String, PoolEntry<String>> {
+
+        public LocalSessionPool(
+                final ConnectingIOReactor ioreactor,
+                final PoolEntryFactory<String, PoolEntry<String>> factory,
+                final RouteResolver<String> routeResolver,
+                int defaultMaxPerRoute, int maxTotal) {
+            super(ioreactor, factory, routeResolver, defaultMaxPerRoute, maxTotal);
+        }
+
+        public LocalSessionPool(
+                final ConnectingIOReactor ioreactor, int defaultMaxPerRoute, int maxTotal) {
+            super(ioreactor, new LocalPoolEntryFactory(), new LocalRouteResolver(), defaultMaxPerRoute, maxTotal);
+        }
+
+    }
+
+    @Test
+    public void testEmptyPool() throws Exception {
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 10);
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+        Assert.assertEquals(10, totals.getMax());
+        PoolStats stats = pool.getStats("somehost");
+        Assert.assertEquals(0, stats.getAvailable());
+        Assert.assertEquals(0, stats.getLeased());
+        Assert.assertEquals(0, stats.getPending());
+        Assert.assertEquals(2, stats.getMax());
+        Assert.assertEquals("[leased: []][available: []][pending: []]", pool.toString());
+    }
+
+    @Test
+    public void testInternalLeaseRequest() throws Exception {
+        LeaseRequest<String, PoolEntry<String>> leaseRequest =
+            new LeaseRequest<String, PoolEntry<String>>("somehost", null, 0,
+                    new BasicPoolEntryCallback());
+        Assert.assertEquals("[somehost][null]", leaseRequest.toString());
+    }
+
+    @Test
+    public void testInvalidConstruction() throws Exception {
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        try {
+            new LocalSessionPool(null, new LocalPoolEntryFactory(), new LocalRouteResolver(), 1, 1);
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            new LocalSessionPool(ioreactor, null, new LocalRouteResolver(), 1, 1);
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            new LocalSessionPool(ioreactor, new LocalPoolEntryFactory(), null, 1, 1);
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            new LocalSessionPool(ioreactor, new LocalPoolEntryFactory(), new LocalRouteResolver(), -1, 1);
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            new LocalSessionPool(ioreactor, new LocalPoolEntryFactory(), new LocalRouteResolver(), 1, -1);
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testSuccessfulConnect() throws Exception {
+        IOSession iosession = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest.getSession()).thenReturn(iosession);
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        Mockito.when(ioreactor.connect(
+                Mockito.any(SocketAddress.class),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 10);
+        BasicPoolEntryCallback callback = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, 100, TimeUnit.MILLISECONDS, callback);
+        Mockito.verify(sessionRequest).setConnectTimeout(100);
+
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(1, totals.getPending());
+
+        pool.requestCompleted(sessionRequest);
+        Assert.assertTrue(callback.isCompleted());
+        Assert.assertFalse(callback.isFailed());
+        Assert.assertFalse(callback.isCancelled());
+
+        totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(1, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+    }
+
+    @Test
+    public void testFailedConnect() throws Exception {
+        IOSession iosession = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest.getSession()).thenReturn(iosession);
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        Mockito.when(ioreactor.connect(
+                Mockito.any(SocketAddress.class),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 10);
+        BasicPoolEntryCallback callback = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback);
+
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(1, totals.getPending());
+
+        pool.requestFailed(sessionRequest);
+        Assert.assertFalse(callback.isCompleted());
+        Assert.assertTrue(callback.isFailed());
+        Assert.assertFalse(callback.isCancelled());
+
+        totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+    }
+
+    @Test
+    public void testCencelledConnect() throws Exception {
+        IOSession iosession = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest.getSession()).thenReturn(iosession);
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        Mockito.when(ioreactor.connect(
+                Mockito.any(SocketAddress.class),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 10);
+        BasicPoolEntryCallback callback = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback);
+
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(1, totals.getPending());
+
+        pool.requestCancelled(sessionRequest);
+        Assert.assertFalse(callback.isCompleted());
+        Assert.assertFalse(callback.isFailed());
+        Assert.assertTrue(callback.isCancelled());
+
+        totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+    }
+
+    @Test
+    public void testTimeoutConnect() throws Exception {
+        IOSession iosession = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest.getSession()).thenReturn(iosession);
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        Mockito.when(ioreactor.connect(
+                Mockito.any(SocketAddress.class),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 10);
+        BasicPoolEntryCallback callback = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback);
+
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(1, totals.getPending());
+
+        pool.requestTimeout(sessionRequest);
+        Assert.assertFalse(callback.isCompleted());
+        Assert.assertTrue(callback.isFailed());
+        Assert.assertFalse(callback.isCancelled());
+        Assert.assertTrue(callback.getException() instanceof SocketTimeoutException);
+
+        totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+    }
+
+    @Test
+    public void testLeaseRelease() throws Exception {
+        IOSession iosession1 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest1.getSession()).thenReturn(iosession1);
+
+        IOSession iosession2 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest2.getAttachment()).thenReturn("otherhost");
+        Mockito.when(sessionRequest2.getSession()).thenReturn(iosession2);
+
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        Mockito.when(ioreactor.connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("somehost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest1);
+        Mockito.when(ioreactor.connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest2);
+
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 10);
+        BasicPoolEntryCallback callback1 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback1);
+        pool.requestCompleted(sessionRequest1);
+        BasicPoolEntryCallback callback2 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback2);
+        pool.requestCompleted(sessionRequest1);
+        BasicPoolEntryCallback callback3 = new BasicPoolEntryCallback();
+        pool.lease("otherhost", null, -1, TimeUnit.MILLISECONDS, callback3);
+        pool.requestCompleted(sessionRequest2);
+
+        PoolEntry<String> entry1 = callback1.getEntry();
+        Assert.assertNotNull(entry1);
+        PoolEntry<String> entry2 = callback2.getEntry();
+        Assert.assertNotNull(entry2);
+        PoolEntry<String> entry3 = callback3.getEntry();
+        Assert.assertNotNull(entry3);
+
+        pool.release(entry1, true);
+        pool.release(entry2, true);
+        pool.release(entry3, false);
+        Mockito.verify(iosession1, Mockito.never()).close();
+        Mockito.verify(iosession2, Mockito.times(1)).close();
+
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(2, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+    }
+
+    @Test
+    public void testLeaseIllegal() throws Exception {
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 10);
+        try {
+            pool.lease(null, null, 0, TimeUnit.MILLISECONDS, new BasicPoolEntryCallback());
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            pool.lease("somehost", null, 0, null, new BasicPoolEntryCallback());
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            pool.lease("somehost", null, 0, TimeUnit.MILLISECONDS, null);
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testReleaseUnknownEntry() throws Exception {
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 2);
+        pool.release(new LocalPoolEntry(
+                "somehost", Mockito.mock(IOSession.class), 1000, TimeUnit.SECONDS), true);
+    }
+
+    @Test
+    public void testMaxLimits() throws Exception {
+        IOSession iosession1 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest1.getSession()).thenReturn(iosession1);
+
+        IOSession iosession2 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest2.getAttachment()).thenReturn("otherhost");
+        Mockito.when(sessionRequest2.getSession()).thenReturn(iosession2);
+
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        Mockito.when(ioreactor.connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("somehost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest1);
+        Mockito.when(ioreactor.connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest2);
+
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 10);
+        pool.setMaxPerHost("somehost", 2);
+        pool.setMaxPerHost("otherhost", 1);
+        pool.setTotalMax(3);
+
+        BasicPoolEntryCallback callback1 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback1);
+        pool.requestCompleted(sessionRequest1);
+        BasicPoolEntryCallback callback2 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback2);
+        pool.requestCompleted(sessionRequest1);
+        BasicPoolEntryCallback callback3 = new BasicPoolEntryCallback();
+        pool.lease("otherhost", null, -1, TimeUnit.MILLISECONDS, callback3);
+        pool.requestCompleted(sessionRequest2);
+
+        PoolEntry<String> entry1 = callback1.getEntry();
+        Assert.assertNotNull(entry1);
+        PoolEntry<String> entry2 = callback2.getEntry();
+        Assert.assertNotNull(entry2);
+        PoolEntry<String> entry3 = callback3.getEntry();
+        Assert.assertNotNull(entry3);
+
+        pool.release(entry1, true);
+        pool.release(entry2, true);
+        pool.release(entry3, true);
+
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(3, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+
+        BasicPoolEntryCallback callback4 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback4);
+        BasicPoolEntryCallback callback5 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback5);
+        BasicPoolEntryCallback callback6 = new BasicPoolEntryCallback();
+        pool.lease("otherhost", null, -1, TimeUnit.MILLISECONDS, callback6);
+        BasicPoolEntryCallback callback7 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback7);
+        BasicPoolEntryCallback callback8 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback8);
+        BasicPoolEntryCallback callback9 = new BasicPoolEntryCallback();
+        pool.lease("otherhost", null, -1, TimeUnit.MILLISECONDS, callback9);
+
+        Assert.assertTrue(callback4.isCompleted());
+        PoolEntry<String> entry4 = callback4.getEntry();
+        Assert.assertNotNull(entry4);
+        Assert.assertTrue(callback5.isCompleted());
+        PoolEntry<String> entry5 = callback5.getEntry();
+        Assert.assertNotNull(entry5);
+        Assert.assertTrue(callback6.isCompleted());
+        PoolEntry<String> entry6 = callback6.getEntry();
+        Assert.assertNotNull(entry6);
+        Assert.assertFalse(callback7.isCompleted());
+        Assert.assertFalse(callback8.isCompleted());
+        Assert.assertFalse(callback9.isCompleted());
+
+        Mockito.verify(ioreactor, Mockito.times(3)).connect(
+                Mockito.any(SocketAddress.class), Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        pool.release(entry4, true);
+        pool.release(entry5, false);
+        pool.release(entry6, true);
+
+        Assert.assertTrue(callback7.isCompleted());
+        Assert.assertFalse(callback8.isCompleted());
+        Assert.assertTrue(callback9.isCompleted());
+
+        Mockito.verify(ioreactor, Mockito.times(4)).connect(
+                Mockito.any(SocketAddress.class), Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+    }
+
+    @Test
+    public void testConnectionRedistributionOnTotalMaxLimit() throws Exception {
+        IOSession iosession1 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest1.getSession()).thenReturn(iosession1);
+
+        IOSession iosession2 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest2.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest2.getSession()).thenReturn(iosession2);
+
+        IOSession iosession3 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest3 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest3.getAttachment()).thenReturn("otherhost");
+        Mockito.when(sessionRequest3.getSession()).thenReturn(iosession3);
+
+        IOSession iosession4 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest4 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest4.getAttachment()).thenReturn("otherhost");
+        Mockito.when(sessionRequest4.getSession()).thenReturn(iosession4);
+
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        Mockito.when(ioreactor.connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("somehost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest1, sessionRequest2, sessionRequest1);
+        Mockito.when(ioreactor.connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest3, sessionRequest4, sessionRequest3);
+
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 10);
+        pool.setMaxPerHost("somehost", 2);
+        pool.setMaxPerHost("otherhost", 2);
+        pool.setTotalMax(2);
+
+        BasicPoolEntryCallback callback1 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback1);
+        BasicPoolEntryCallback callback2 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback2);
+        BasicPoolEntryCallback callback3 = new BasicPoolEntryCallback();
+        pool.lease("otherhost", null, -1, TimeUnit.MILLISECONDS, callback3);
+        BasicPoolEntryCallback callback4 = new BasicPoolEntryCallback();
+        pool.lease("otherhost", null, -1, TimeUnit.MILLISECONDS, callback4);
+
+        Mockito.verify(ioreactor, Mockito.times(2)).connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("somehost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        Mockito.verify(ioreactor, Mockito.never()).connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        pool.requestCompleted(sessionRequest1);
+        pool.requestCompleted(sessionRequest2);
+
+        Assert.assertTrue(callback1.isCompleted());
+        PoolEntry<String> entry1 = callback1.getEntry();
+        Assert.assertNotNull(entry1);
+        Assert.assertTrue(callback2.isCompleted());
+        PoolEntry<String> entry2 = callback2.getEntry();
+        Assert.assertNotNull(entry2);
+
+        Assert.assertFalse(callback3.isCompleted());
+        Assert.assertFalse(callback4.isCompleted());
+
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(2, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+
+        pool.release(entry1, true);
+        pool.release(entry2, true);
+
+        Mockito.verify(ioreactor, Mockito.times(2)).connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("somehost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        Mockito.verify(ioreactor, Mockito.times(2)).connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        pool.requestCompleted(sessionRequest3);
+        pool.requestCompleted(sessionRequest4);
+
+        Assert.assertTrue(callback3.isCompleted());
+        PoolEntry<String> entry3 = callback3.getEntry();
+        Assert.assertNotNull(entry3);
+        Assert.assertTrue(callback4.isCompleted());
+        PoolEntry<String> entry4 = callback4.getEntry();
+        Assert.assertNotNull(entry4);
+
+        totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(2, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+
+        BasicPoolEntryCallback callback5 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback5);
+        BasicPoolEntryCallback callback6 = new BasicPoolEntryCallback();
+        pool.lease("otherhost", null, -1, TimeUnit.MILLISECONDS, callback6);
+
+        Mockito.verify(ioreactor, Mockito.times(2)).connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("somehost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        Mockito.verify(ioreactor, Mockito.times(2)).connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        pool.release(entry3, true);
+        pool.release(entry4, true);
+
+        Mockito.verify(ioreactor, Mockito.times(3)).connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("somehost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        Mockito.verify(ioreactor, Mockito.times(2)).connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        pool.requestCompleted(sessionRequest1);
+
+        Assert.assertTrue(callback5.isCompleted());
+        PoolEntry<String> entry5 = callback5.getEntry();
+        Assert.assertNotNull(entry5);
+        Assert.assertTrue(callback6.isCompleted());
+        PoolEntry<String> entry6 = callback6.getEntry();
+        Assert.assertNotNull(entry6);
+
+        totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(2, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+
+        pool.release(entry5, true);
+        pool.release(entry6, true);
+
+        Mockito.verify(ioreactor, Mockito.times(3)).connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("somehost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        Mockito.verify(ioreactor, Mockito.times(2)).connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        totals = pool.getTotalStats();
+        Assert.assertEquals(2, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+    }
+
+    @Test
+    public void testCreateNewIfExpired() throws Exception {
+        IOSession iosession1 = Mockito.mock(IOSession.class);
+        Mockito.when(iosession1.isClosed()).thenReturn(Boolean.TRUE);
+        SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest1.getSession()).thenReturn(iosession1);
+
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        Mockito.when(ioreactor.connect(
+                Mockito.eq(InetSocketAddress.createUnresolved("somehost", 80)),
+                Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest1);
+
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 2);
+
+        BasicPoolEntryCallback callback1 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback1);
+
+        Mockito.verify(ioreactor, Mockito.times(1)).connect(
+                Mockito.any(SocketAddress.class), Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        pool.requestCompleted(sessionRequest1);
+
+        Assert.assertTrue(callback1.isCompleted());
+        PoolEntry<String> entry1 = callback1.getEntry();
+        Assert.assertNotNull(entry1);
+
+        entry1.updateExpiry(1, TimeUnit.MILLISECONDS);
+        pool.release(entry1, true);
+
+        Thread.sleep(200L);
+
+        BasicPoolEntryCallback callback2 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback2);
+
+        Assert.assertFalse(callback2.isCompleted());
+
+        Mockito.verify(iosession1).close();
+        Mockito.verify(ioreactor, Mockito.times(2)).connect(
+                Mockito.any(SocketAddress.class), Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class));
+
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(1, totals.getPending());
+        PoolStats stats = pool.getStats("somehost");
+        Assert.assertEquals(0, stats.getAvailable());
+        Assert.assertEquals(0, stats.getLeased());
+        Assert.assertEquals(1, stats.getPending());
+    }
+
+    @Test
+    public void testCloseExpired() throws Exception {
+        IOSession iosession1 = Mockito.mock(IOSession.class);
+        Mockito.when(iosession1.isClosed()).thenReturn(Boolean.TRUE);
+        SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest1.getSession()).thenReturn(iosession1);
+
+        IOSession iosession2 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest2.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest2.getSession()).thenReturn(iosession2);
+
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        Mockito.when(ioreactor.connect(
+                Mockito.any(SocketAddress.class), Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest1, sessionRequest2);
+
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 2);
+
+        BasicPoolEntryCallback callback1 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback1);
+        BasicPoolEntryCallback callback2 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback2);
+
+        pool.requestCompleted(sessionRequest1);
+        pool.requestCompleted(sessionRequest2);
+
+        Assert.assertTrue(callback1.isCompleted());
+        PoolEntry<String> entry1 = callback1.getEntry();
+        Assert.assertNotNull(entry1);
+        Assert.assertTrue(callback2.isCompleted());
+        PoolEntry<String> entry2 = callback2.getEntry();
+        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(iosession1).close();
+        Mockito.verify(iosession2, Mockito.never()).close();
+
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(1, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+        PoolStats stats = pool.getStats("somehost");
+        Assert.assertEquals(1, stats.getAvailable());
+        Assert.assertEquals(0, stats.getLeased());
+        Assert.assertEquals(0, stats.getPending());
+    }
+
+    @Test
+    public void testCloseIdle() throws Exception {
+        IOSession iosession1 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest1.getSession()).thenReturn(iosession1);
+
+        IOSession iosession2 = Mockito.mock(IOSession.class);
+        SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
+        Mockito.when(sessionRequest2.getAttachment()).thenReturn("somehost");
+        Mockito.when(sessionRequest2.getSession()).thenReturn(iosession2);
+
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        Mockito.when(ioreactor.connect(
+                Mockito.any(SocketAddress.class), Mockito.any(SocketAddress.class),
+                Mockito.any(), Mockito.any(SessionRequestCallback.class))).
+                thenReturn(sessionRequest1, sessionRequest2);
+
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 2);
+
+        BasicPoolEntryCallback callback1 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback1);
+        BasicPoolEntryCallback callback2 = new BasicPoolEntryCallback();
+        pool.lease("somehost", null, -1, TimeUnit.MILLISECONDS, callback2);
+
+        pool.requestCompleted(sessionRequest1);
+        pool.requestCompleted(sessionRequest2);
+
+        Assert.assertTrue(callback1.isCompleted());
+        PoolEntry<String> entry1 = callback1.getEntry();
+        Assert.assertNotNull(entry1);
+        Assert.assertTrue(callback2.isCompleted());
+        PoolEntry<String> entry2 = callback2.getEntry();
+        Assert.assertNotNull(entry2);
+
+        entry1.updateExpiry(0, TimeUnit.MILLISECONDS);
+        pool.release(entry1, true);
+
+        Thread.sleep(200L);
+
+        entry2.updateExpiry(0, TimeUnit.MILLISECONDS);
+        pool.release(entry2, true);
+
+        pool.closeIdle(50, TimeUnit.MILLISECONDS);
+
+        Mockito.verify(iosession1).close();
+        Mockito.verify(iosession2, Mockito.never()).close();
+
+        PoolStats totals = pool.getTotalStats();
+        Assert.assertEquals(1, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+        PoolStats stats = pool.getStats("somehost");
+        Assert.assertEquals(1, stats.getAvailable());
+        Assert.assertEquals(0, stats.getLeased());
+        Assert.assertEquals(0, stats.getPending());
+
+        pool.closeIdle(-1, TimeUnit.MILLISECONDS);
+
+        Mockito.verify(iosession2).close();
+
+        totals = pool.getTotalStats();
+        Assert.assertEquals(0, totals.getAvailable());
+        Assert.assertEquals(0, totals.getLeased());
+        Assert.assertEquals(0, totals.getPending());
+        stats = pool.getStats("somehost");
+        Assert.assertEquals(0, stats.getAvailable());
+        Assert.assertEquals(0, stats.getLeased());
+        Assert.assertEquals(0, stats.getPending());
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testCloseIdleInvalid() throws Exception {
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 2);
+        pool.closeIdle(50, null);
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testGetStatsInvalid() throws Exception {
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 2);
+        pool.getStats(null);
+    }
+
+    @Test
+    public void testSetMaxInvalid() throws Exception {
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 2);
+        try {
+            pool.setTotalMax(-1);
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            pool.setMaxPerHost(null, 1);
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            pool.setMaxPerHost("somehost", -1);
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            pool.setDefaultMaxPerHost(-1);
+            Assert.fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testShutdown() throws Exception {
+        ConnectingIOReactor ioreactor = Mockito.mock(ConnectingIOReactor.class);
+        LocalSessionPool pool = new LocalSessionPool(ioreactor, 2, 2);
+        pool.shutdown(1000);
+        Mockito.verify(ioreactor, Mockito.times(1)).shutdown(1000);
+        pool.shutdown(1000);
+        Mockito.verify(ioreactor, Mockito.times(1)).shutdown(1000);
+        try {
+            pool.lease("somehost", null, 0, TimeUnit.MILLISECONDS, new BasicPoolEntryCallback());
+            Assert.fail("IllegalStateException should have been thrown");
+        } catch (IllegalStateException expected) {
+        }
+        // Ignored if shut down
+        pool.release(new LocalPoolEntry("somehost", Mockito.mock(IOSession.class), 1000, TimeUnit.SECONDS), true);
+        pool.requestCompleted(Mockito.mock(SessionRequest.class));
+        pool.requestFailed(Mockito.mock(SessionRequest.class));
+        pool.requestCancelled(Mockito.mock(SessionRequest.class));
+        pool.requestTimeout(Mockito.mock(SessionRequest.class));
+    }
+
+}

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/pool/TestSessionPool.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/pool/TestSessionPool.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpasyncclient/trunk/httpasyncclient/src/test/java/org/apache/http/impl/nio/pool/TestSessionPool.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain