View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.pool;
28  
29  import java.io.IOException;
30  import java.util.concurrent.Future;
31  
32  import org.apache.http.HttpConnection;
33  import org.junit.Assert;
34  import org.junit.Test;
35  import org.mockito.Mockito;
36  
37  public class TestRouteSpecificPool {
38  
39      private static final String ROUTE = "whatever";
40  
41      static class LocalPoolEntry extends PoolEntry<String, HttpConnection> {
42  
43          public LocalPoolEntry(final String route, final HttpConnection conn) {
44              super(null, route, conn);
45          }
46  
47          @Override
48          public void close() {
49              try {
50                  getConnection().close();
51              } catch (final IOException ignore) {
52              }
53          }
54  
55          @Override
56          public boolean isClosed() {
57              return !getConnection().isOpen();
58          }
59  
60      }
61  
62      static class LocalRoutePool extends RouteSpecificPool<String, HttpConnection, LocalPoolEntry> {
63  
64          public LocalRoutePool() {
65              super(ROUTE);
66          }
67  
68          @Override
69          protected LocalPoolEntry createEntry(final HttpConnection conn) {
70              return new LocalPoolEntry(getRoute(), conn);
71          }
72  
73      }
74  
75      @Test
76      public void testEmptyPool() throws Exception {
77          final LocalRoutePool pool = new LocalRoutePool();
78          Assert.assertEquals(ROUTE, pool.getRoute());
79          Assert.assertEquals(0, pool.getAllocatedCount());
80          Assert.assertEquals(0, pool.getAvailableCount());
81          Assert.assertEquals(0, pool.getLeasedCount());
82          Assert.assertEquals(0, pool.getPendingCount());
83          Assert.assertNull(pool.getLastUsed());
84          Assert.assertEquals("[route: whatever][leased: 0][available: 0][pending: 0]", pool.toString());
85      }
86  
87      @Test
88      public void testAdd() throws Exception {
89          final LocalRoutePool pool = new LocalRoutePool();
90          final HttpConnection conn = Mockito.mock(HttpConnection.class);
91          final PoolEntry<String, HttpConnection> entry = pool.add(conn);
92          Assert.assertEquals(1, pool.getAllocatedCount());
93          Assert.assertEquals(0, pool.getAvailableCount());
94          Assert.assertEquals(1, pool.getLeasedCount());
95          Assert.assertEquals(0, pool.getPendingCount());
96          Assert.assertNotNull(entry);
97          Assert.assertSame(conn, entry.getConnection());
98      }
99  
100     @Test
101     public void testLeaseRelease() throws Exception {
102         final LocalRoutePool pool = new LocalRoutePool();
103         final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
104         final LocalPoolEntry entry1 = pool.add(conn1);
105         final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
106         final LocalPoolEntry entry2 = pool.add(conn2);
107         final HttpConnection conn3 = Mockito.mock(HttpConnection.class);
108         final LocalPoolEntry entry3 = pool.add(conn3);
109 
110         Assert.assertNotNull(entry1);
111         Assert.assertNotNull(entry2);
112         Assert.assertNotNull(entry3);
113 
114         Assert.assertEquals(3, pool.getAllocatedCount());
115         Assert.assertEquals(0, pool.getAvailableCount());
116         Assert.assertEquals(3, pool.getLeasedCount());
117         Assert.assertEquals(0, pool.getPendingCount());
118 
119         pool.free(entry1, true);
120         pool.free(entry2, false);
121         pool.free(entry3, true);
122 
123         Assert.assertEquals(2, pool.getAllocatedCount());
124         Assert.assertEquals(2, pool.getAvailableCount());
125         Assert.assertEquals(0, pool.getLeasedCount());
126         Assert.assertEquals(0, pool.getPendingCount());
127 
128         Assert.assertSame(entry1, pool.getLastUsed());
129 
130         Assert.assertNotNull(pool.getFree(null));
131         Assert.assertNotNull(pool.getFree(null));
132         Assert.assertNull(pool.getFree(null));
133 
134         Assert.assertEquals(2, pool.getAllocatedCount());
135         Assert.assertEquals(0, pool.getAvailableCount());
136         Assert.assertEquals(2, pool.getLeasedCount());
137         Assert.assertEquals(0, pool.getPendingCount());
138     }
139 
140     @Test
141     public void testLeaseOrder() throws Exception {
142         final LocalRoutePool pool = new LocalRoutePool();
143         final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
144         final LocalPoolEntry entry1 = pool.add(conn1);
145         final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
146         final LocalPoolEntry entry2 = pool.add(conn2);
147         final HttpConnection conn3 = Mockito.mock(HttpConnection.class);
148         final LocalPoolEntry entry3 = pool.add(conn3);
149 
150         Assert.assertNotNull(entry1);
151         Assert.assertNotNull(entry2);
152         Assert.assertNotNull(entry3);
153 
154         Assert.assertEquals(3, pool.getAllocatedCount());
155         Assert.assertEquals(0, pool.getAvailableCount());
156         Assert.assertEquals(3, pool.getLeasedCount());
157         Assert.assertEquals(0, pool.getPendingCount());
158 
159         pool.free(entry1, true);
160         pool.free(entry2, true);
161         pool.free(entry3, true);
162 
163         Assert.assertSame(entry1, pool.getLastUsed());
164 
165         Assert.assertSame(entry3, pool.getFree(null));
166         Assert.assertSame(entry2, pool.getFree(null));
167         Assert.assertSame(entry1, pool.getFree(null));
168     }
169 
170     @Test
171     public void testLeaseReleaseStateful() throws Exception {
172         final LocalRoutePool pool = new LocalRoutePool();
173         final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
174         final LocalPoolEntry entry1 = pool.add(conn1);
175         final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
176         final LocalPoolEntry entry2 = pool.add(conn2);
177         final HttpConnection conn3 = Mockito.mock(HttpConnection.class);
178         final LocalPoolEntry entry3 = pool.add(conn3);
179 
180         Assert.assertNotNull(entry1);
181         Assert.assertNotNull(entry2);
182         Assert.assertNotNull(entry3);
183 
184         Assert.assertEquals(3, pool.getAllocatedCount());
185         Assert.assertEquals(0, pool.getAvailableCount());
186         Assert.assertEquals(3, pool.getLeasedCount());
187         Assert.assertEquals(0, pool.getPendingCount());
188 
189         entry2.setState(Boolean.FALSE);
190         pool.free(entry1, true);
191         pool.free(entry2, true);
192         pool.free(entry3, true);
193 
194         Assert.assertSame(entry2, pool.getFree(Boolean.FALSE));
195         Assert.assertSame(entry3, pool.getFree(Boolean.FALSE));
196         Assert.assertSame(entry1, pool.getFree(null));
197         Assert.assertSame(null, pool.getFree(null));
198 
199         entry1.setState(Boolean.TRUE);
200         entry2.setState(Boolean.FALSE);
201         entry3.setState(Boolean.TRUE);
202         pool.free(entry1, true);
203         pool.free(entry2, true);
204         pool.free(entry3, true);
205 
206         Assert.assertSame(null, pool.getFree(null));
207         Assert.assertSame(entry2, pool.getFree(Boolean.FALSE));
208         Assert.assertSame(null, pool.getFree(Boolean.FALSE));
209         Assert.assertSame(entry3, pool.getFree(Boolean.TRUE));
210         Assert.assertSame(entry1, pool.getFree(Boolean.TRUE));
211         Assert.assertSame(null, pool.getFree(Boolean.TRUE));
212     }
213 
214     @Test(expected=IllegalStateException.class)
215     public void testReleaseInvalidEntry() throws Exception {
216         final LocalRoutePool pool = new LocalRoutePool();
217         final HttpConnection conn = Mockito.mock(HttpConnection.class);
218         final LocalPoolEntry entry = new LocalPoolEntry(ROUTE, conn);
219         pool.free(entry, true);
220     }
221 
222     @Test
223     public void testRemove() throws Exception {
224         final LocalRoutePool pool = new LocalRoutePool();
225         final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
226         final LocalPoolEntry entry1 = pool.add(conn1);
227         final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
228         final LocalPoolEntry entry2 = pool.add(conn2);
229         final HttpConnection conn3 = Mockito.mock(HttpConnection.class);
230         final LocalPoolEntry entry3 = pool.add(conn3);
231 
232         Assert.assertNotNull(entry1);
233         Assert.assertNotNull(entry2);
234         Assert.assertNotNull(entry3);
235 
236         Assert.assertEquals(3, pool.getAllocatedCount());
237         Assert.assertEquals(0, pool.getAvailableCount());
238         Assert.assertEquals(3, pool.getLeasedCount());
239         Assert.assertEquals(0, pool.getPendingCount());
240 
241         Assert.assertTrue(pool.remove(entry2));
242         Assert.assertFalse(pool.remove(entry2));
243 
244         Assert.assertEquals(2, pool.getAllocatedCount());
245         Assert.assertEquals(0, pool.getAvailableCount());
246         Assert.assertEquals(2, pool.getLeasedCount());
247         Assert.assertEquals(0, pool.getPendingCount());
248 
249         pool.free(entry1, true);
250         pool.free(entry3, true);
251 
252         Assert.assertEquals(2, pool.getAllocatedCount());
253         Assert.assertEquals(2, pool.getAvailableCount());
254         Assert.assertEquals(0, pool.getLeasedCount());
255         Assert.assertEquals(0, pool.getPendingCount());
256 
257         Assert.assertTrue(pool.remove(entry1));
258         Assert.assertTrue(pool.remove(entry3));
259 
260         Assert.assertEquals(0, pool.getAllocatedCount());
261         Assert.assertEquals(0, pool.getAvailableCount());
262         Assert.assertEquals(0, pool.getLeasedCount());
263         Assert.assertEquals(0, pool.getPendingCount());
264     }
265 
266     @Test(expected=IllegalArgumentException.class)
267     public void testReleaseInvalid() throws Exception {
268         final LocalRoutePool pool = new LocalRoutePool();
269         pool.free(null, true);
270     }
271 
272     @Test(expected=IllegalArgumentException.class)
273     public void testRemoveInvalid() throws Exception {
274         final LocalRoutePool pool = new LocalRoutePool();
275         pool.remove(null);
276     }
277 
278     @Test
279     public void testWaitingThreadQueuing() throws Exception {
280         final LocalRoutePool pool = new LocalRoutePool();
281         @SuppressWarnings("unchecked")
282         final Future<LocalPoolEntry> future1 = Mockito.mock(Future.class);
283         @SuppressWarnings("unchecked")
284         final Future<LocalPoolEntry> future2 = Mockito.mock(Future.class);
285 
286         Assert.assertEquals(0, pool.getPendingCount());
287         pool.queue(future1);
288         Assert.assertEquals(1, pool.getPendingCount());
289         pool.queue(null);
290         Assert.assertEquals(1, pool.getPendingCount());
291         pool.queue(future2);
292         Assert.assertEquals(2, pool.getPendingCount());
293         Assert.assertSame(future1, pool.nextPending());
294         pool.unqueue(future1);
295         Assert.assertEquals(1, pool.getPendingCount());
296         Assert.assertSame(future2, pool.nextPending());
297         pool.unqueue(null);
298         Assert.assertEquals(0, pool.getPendingCount());
299         pool.unqueue(future2);
300         Assert.assertNull(pool.nextPending());
301     }
302 
303     @Test
304     public void testShutdown() throws Exception {
305         final LocalRoutePool pool = new LocalRoutePool();
306         final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
307         final LocalPoolEntry entry1 = pool.add(conn1);
308         final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
309         final LocalPoolEntry entry2 = pool.add(conn2);
310 
311         @SuppressWarnings("unchecked")
312         final Future<LocalPoolEntry> future1 = Mockito.mock(Future.class);
313         pool.queue(future1);
314 
315         Assert.assertNotNull(entry1);
316         Assert.assertNotNull(entry2);
317 
318         pool.free(entry1, true);
319 
320         Assert.assertEquals(2, pool.getAllocatedCount());
321         Assert.assertEquals(1, pool.getAvailableCount());
322         Assert.assertEquals(1, pool.getLeasedCount());
323         Assert.assertEquals(1, pool.getPendingCount());
324 
325         pool.shutdown();
326 
327         Assert.assertEquals(0, pool.getAllocatedCount());
328         Assert.assertEquals(0, pool.getAvailableCount());
329         Assert.assertEquals(0, pool.getLeasedCount());
330         Assert.assertEquals(0, pool.getPendingCount());
331 
332         Mockito.verify(future1).cancel(true);
333         Mockito.verify(conn2).close();
334         Mockito.verify(conn1).close();
335     }
336 
337 }