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.nio.pool;
28  
29  import java.io.IOException;
30  import java.net.ConnectException;
31  import java.util.concurrent.ExecutionException;
32  
33  import org.apache.http.concurrent.BasicFuture;
34  import org.apache.http.nio.reactor.IOSession;
35  import org.apache.http.nio.reactor.SessionRequest;
36  import org.apache.http.pool.PoolEntry;
37  import org.junit.Assert;
38  import org.junit.Test;
39  import org.mockito.Mockito;
40  
41  public class TestRouteSpecificPool {
42  
43      static class LocalPoolEntry extends PoolEntry<String, IOSession> {
44  
45          public LocalPoolEntry(final String route, final IOSession conn) {
46              super(null, route, conn);
47          }
48  
49          @Override
50          public void close() {
51              getConnection().close();
52          }
53  
54          @Override
55          public boolean isClosed() {
56              return getConnection().isClosed();
57          }
58  
59      }
60  
61      static class LocalRoutePool extends RouteSpecificPool<String, IOSession, LocalPoolEntry> {
62  
63          public LocalRoutePool() {
64              super("whatever");
65          }
66  
67          @Override
68          protected LocalPoolEntry createEntry(final String route, final IOSession session) {
69              return new LocalPoolEntry(route, session);
70          }
71  
72      }
73  
74      @Test
75      public void testEmptyPool() throws Exception {
76          final LocalRoutePool pool = new LocalRoutePool();
77          Assert.assertEquals(0, pool.getAllocatedCount());
78          Assert.assertEquals(0, pool.getAvailableCount());
79          Assert.assertEquals(0, pool.getLeasedCount());
80          Assert.assertEquals(0, pool.getPendingCount());
81          Assert.assertNull(pool.getLastUsed());
82          Assert.assertEquals("[route: whatever][leased: 0][available: 0][pending: 0]", pool.toString());
83      }
84  
85      @Test
86      public void testSuccessfulConnect() throws Exception {
87          final LocalRoutePool pool = new LocalRoutePool();
88          final IOSession session = Mockito.mock(IOSession.class);
89          final SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
90          Mockito.when(sessionRequest.getSession()).thenReturn(session);
91          final BasicFuture<LocalPoolEntry> future = new BasicFuture<LocalPoolEntry>(null);
92          pool.addPending(sessionRequest, future);
93          Assert.assertEquals(1, pool.getAllocatedCount());
94          Assert.assertEquals(0, pool.getAvailableCount());
95          Assert.assertEquals(0, pool.getLeasedCount());
96          Assert.assertEquals(1, pool.getPendingCount());
97          final LocalPoolEntry entry = pool.createEntry(sessionRequest, session);
98          Assert.assertNotNull(entry);
99          Assert.assertSame(session, entry.getConnection());
100         Assert.assertFalse(future.isDone());
101         Assert.assertFalse(future.isCancelled());
102         pool.completed(sessionRequest, entry);
103         Assert.assertTrue(future.isDone());
104         Assert.assertFalse(future.isCancelled());
105 
106         Assert.assertEquals(1, pool.getAllocatedCount());
107         Assert.assertEquals(0, pool.getAvailableCount());
108         Assert.assertEquals(1, pool.getLeasedCount());
109         Assert.assertEquals(0, pool.getPendingCount());
110     }
111 
112     @Test
113     public void testFailedConnect() throws Exception {
114         final LocalRoutePool pool = new LocalRoutePool();
115         final SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
116         final BasicFuture<LocalPoolEntry> future = new BasicFuture<LocalPoolEntry>(null);
117         pool.addPending(sessionRequest, future);
118         Assert.assertEquals(1, pool.getAllocatedCount());
119         Assert.assertEquals(0, pool.getAvailableCount());
120         Assert.assertEquals(0, pool.getLeasedCount());
121         Assert.assertEquals(1, pool.getPendingCount());
122         pool.failed(sessionRequest, new IOException());
123         Assert.assertTrue(future.isDone());
124         Assert.assertFalse(future.isCancelled());
125         try {
126             future.get();
127             Assert.fail("ExecutionException should have been thrown");
128         } catch (final ExecutionException ex) {
129             Assert.assertTrue(ex.getCause() instanceof IOException);
130         }
131         Assert.assertEquals(0, pool.getAllocatedCount());
132         Assert.assertEquals(0, pool.getAvailableCount());
133         Assert.assertEquals(0, pool.getLeasedCount());
134         Assert.assertEquals(0, pool.getPendingCount());
135     }
136 
137     @Test
138     public void testCancelledConnect() throws Exception {
139         final LocalRoutePool pool = new LocalRoutePool();
140         final SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
141         final BasicFuture<LocalPoolEntry> future = new BasicFuture<LocalPoolEntry>(null);
142         pool.addPending(sessionRequest, future);
143         Assert.assertEquals(1, pool.getAllocatedCount());
144         Assert.assertEquals(0, pool.getAvailableCount());
145         Assert.assertEquals(0, pool.getLeasedCount());
146         Assert.assertEquals(1, pool.getPendingCount());
147         pool.cancelled(sessionRequest);
148         Assert.assertTrue(future.isDone());
149         Assert.assertTrue(future.isCancelled());
150 
151         Assert.assertEquals(0, pool.getAllocatedCount());
152         Assert.assertEquals(0, pool.getAvailableCount());
153         Assert.assertEquals(0, pool.getLeasedCount());
154         Assert.assertEquals(0, pool.getPendingCount());
155     }
156 
157     @Test
158     public void testConnectTimeout() throws Exception {
159         final LocalRoutePool pool = new LocalRoutePool();
160         final SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
161         final BasicFuture<LocalPoolEntry> future = new BasicFuture<LocalPoolEntry>(null);
162         pool.addPending(sessionRequest, future);
163         Assert.assertEquals(1, pool.getAllocatedCount());
164         Assert.assertEquals(0, pool.getAvailableCount());
165         Assert.assertEquals(0, pool.getLeasedCount());
166         Assert.assertEquals(1, pool.getPendingCount());
167         pool.timeout(sessionRequest);
168         Assert.assertTrue(future.isDone());
169         Assert.assertFalse(future.isCancelled());
170         try {
171             future.get();
172             Assert.fail("ExecutionException should have been thrown");
173         } catch (final ExecutionException ex) {
174             Assert.assertTrue(ex.getCause() instanceof ConnectException);
175         }
176         Assert.assertEquals(0, pool.getAllocatedCount());
177         Assert.assertEquals(0, pool.getAvailableCount());
178         Assert.assertEquals(0, pool.getLeasedCount());
179         Assert.assertEquals(0, pool.getPendingCount());
180     }
181 
182     @Test
183     public void testLeaseRelease() throws Exception {
184         final LocalRoutePool pool = new LocalRoutePool();
185         final IOSession session1 = Mockito.mock(IOSession.class);
186         final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
187         Mockito.when(sessionRequest1.getSession()).thenReturn(session1);
188         final BasicFuture<LocalPoolEntry> future1 = new BasicFuture<LocalPoolEntry>(null);
189         pool.addPending(sessionRequest1, future1);
190         final IOSession session2 = Mockito.mock(IOSession.class);
191         final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
192         Mockito.when(sessionRequest2.getSession()).thenReturn(session2);
193         final BasicFuture<LocalPoolEntry> future2 = new BasicFuture<LocalPoolEntry>(null);
194         pool.addPending(sessionRequest2, future2);
195         final IOSession session3 = Mockito.mock(IOSession.class);
196         final SessionRequest sessionRequest3 = Mockito.mock(SessionRequest.class);
197         Mockito.when(sessionRequest3.getSession()).thenReturn(session3);
198         final BasicFuture<LocalPoolEntry> future3 = new BasicFuture<LocalPoolEntry>(null);
199         pool.addPending(sessionRequest3, future3);
200 
201         Assert.assertEquals(3, pool.getAllocatedCount());
202         Assert.assertEquals(0, pool.getAvailableCount());
203         Assert.assertEquals(0, pool.getLeasedCount());
204         Assert.assertEquals(3, pool.getPendingCount());
205 
206         final LocalPoolEntry entry1 = pool.createEntry(sessionRequest1, session1);
207         pool.completed(sessionRequest1, entry1);
208         Assert.assertNotNull(entry1);
209         final LocalPoolEntry entry2 = pool.createEntry(sessionRequest2, session2);
210         pool.completed(sessionRequest2, entry2);
211         Assert.assertNotNull(entry2);
212         final LocalPoolEntry entry3 = pool.createEntry(sessionRequest3, session3);
213         pool.completed(sessionRequest3, entry3);
214         Assert.assertNotNull(entry3);
215 
216         Assert.assertEquals(3, pool.getAllocatedCount());
217         Assert.assertEquals(0, pool.getAvailableCount());
218         Assert.assertEquals(3, pool.getLeasedCount());
219         Assert.assertEquals(0, pool.getPendingCount());
220 
221         pool.free(entry1, true);
222         pool.free(entry2, false);
223         pool.free(entry3, true);
224 
225         Assert.assertSame(entry1, pool.getLastUsed());
226 
227         Assert.assertEquals(2, pool.getAllocatedCount());
228         Assert.assertEquals(2, pool.getAvailableCount());
229         Assert.assertEquals(0, pool.getLeasedCount());
230         Assert.assertEquals(0, pool.getPendingCount());
231 
232         Assert.assertNotNull(pool.getFree(null));
233         Assert.assertNotNull(pool.getFree(null));
234         Assert.assertNull(pool.getFree(null));
235 
236         Assert.assertEquals(2, pool.getAllocatedCount());
237         Assert.assertEquals(0, pool.getAvailableCount());
238         Assert.assertEquals(2, pool.getLeasedCount());
239         Assert.assertEquals(0, pool.getPendingCount());
240     }
241 
242     @Test
243     public void testLeaseOrder() throws Exception {
244         final LocalRoutePool pool = new LocalRoutePool();
245         final IOSession session1 = Mockito.mock(IOSession.class);
246         final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
247         Mockito.when(sessionRequest1.getSession()).thenReturn(session1);
248         final BasicFuture<LocalPoolEntry> future1 = new BasicFuture<LocalPoolEntry>(null);
249         pool.addPending(sessionRequest1, future1);
250         final IOSession session2 = Mockito.mock(IOSession.class);
251         final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
252         Mockito.when(sessionRequest2.getSession()).thenReturn(session2);
253         final BasicFuture<LocalPoolEntry> future2 = new BasicFuture<LocalPoolEntry>(null);
254         pool.addPending(sessionRequest2, future2);
255         final IOSession session3 = Mockito.mock(IOSession.class);
256         final SessionRequest sessionRequest3 = Mockito.mock(SessionRequest.class);
257         Mockito.when(sessionRequest3.getSession()).thenReturn(session3);
258         final BasicFuture<LocalPoolEntry> future3 = new BasicFuture<LocalPoolEntry>(null);
259         pool.addPending(sessionRequest3, future3);
260 
261         Assert.assertEquals(3, pool.getAllocatedCount());
262         Assert.assertEquals(0, pool.getAvailableCount());
263         Assert.assertEquals(0, pool.getLeasedCount());
264         Assert.assertEquals(3, pool.getPendingCount());
265 
266         final LocalPoolEntry entry1 = pool.createEntry(sessionRequest1, session1);
267         pool.completed(sessionRequest1, entry1);
268         Assert.assertNotNull(entry1);
269         final LocalPoolEntry entry2 = pool.createEntry(sessionRequest2, session2);
270         pool.completed(sessionRequest2, entry2);
271         Assert.assertNotNull(entry2);
272         final LocalPoolEntry entry3 = pool.createEntry(sessionRequest3, session3);
273         pool.completed(sessionRequest3, entry3);
274         Assert.assertNotNull(entry3);
275 
276         Assert.assertEquals(3, pool.getAllocatedCount());
277         Assert.assertEquals(0, pool.getAvailableCount());
278         Assert.assertEquals(3, pool.getLeasedCount());
279         Assert.assertEquals(0, pool.getPendingCount());
280 
281         pool.free(entry1, true);
282         pool.free(entry2, true);
283         pool.free(entry3, true);
284 
285         Assert.assertSame(entry1, pool.getLastUsed());
286 
287         Assert.assertSame(entry3, pool.getFree(null));
288         Assert.assertSame(entry2, pool.getFree(null));
289         Assert.assertSame(entry1, pool.getFree(null));
290     }
291 
292     @Test
293     public void testLeaseReleaseStateful() throws Exception {
294         final LocalRoutePool pool = new LocalRoutePool();
295 
296         final IOSession session1 = Mockito.mock(IOSession.class);
297         final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
298         Mockito.when(sessionRequest1.getSession()).thenReturn(session1);
299         final BasicFuture<LocalPoolEntry> future1 = new BasicFuture<LocalPoolEntry>(null);
300         pool.addPending(sessionRequest1, future1);
301         final IOSession session2 = Mockito.mock(IOSession.class);
302         final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
303         Mockito.when(sessionRequest2.getSession()).thenReturn(session2);
304         final BasicFuture<LocalPoolEntry> future2 = new BasicFuture<LocalPoolEntry>(null);
305         pool.addPending(sessionRequest2, future2);
306         final IOSession session3 = Mockito.mock(IOSession.class);
307         final SessionRequest sessionRequest3 = Mockito.mock(SessionRequest.class);
308         Mockito.when(sessionRequest3.getSession()).thenReturn(session3);
309         final BasicFuture<LocalPoolEntry> future3 = new BasicFuture<LocalPoolEntry>(null);
310         pool.addPending(sessionRequest3, future3);
311 
312         final LocalPoolEntry entry1 = pool.createEntry(sessionRequest1, session1);
313         pool.completed(sessionRequest1, entry1);
314         Assert.assertNotNull(entry1);
315         final LocalPoolEntry entry2 = pool.createEntry(sessionRequest2, session2);
316         pool.completed(sessionRequest2, entry2);
317         Assert.assertNotNull(entry2);
318         final LocalPoolEntry entry3 = pool.createEntry(sessionRequest3, session3);
319         pool.completed(sessionRequest3, entry3);
320         Assert.assertNotNull(entry3);
321 
322         entry2.setState(Boolean.FALSE);
323         pool.free(entry1, true);
324         pool.free(entry2, true);
325         pool.free(entry3, true);
326 
327         Assert.assertSame(entry2, pool.getFree(Boolean.FALSE));
328         Assert.assertSame(entry3, pool.getFree(Boolean.FALSE));
329         Assert.assertSame(entry1, pool.getFree(null));
330         Assert.assertSame(null, pool.getFree(null));
331 
332         entry1.setState(Boolean.TRUE);
333         entry2.setState(Boolean.FALSE);
334         entry3.setState(Boolean.TRUE);
335         pool.free(entry1, true);
336         pool.free(entry2, true);
337         pool.free(entry3, true);
338 
339         Assert.assertSame(null, pool.getFree(null));
340         Assert.assertSame(entry2, pool.getFree(Boolean.FALSE));
341         Assert.assertSame(null, pool.getFree(Boolean.FALSE));
342         Assert.assertSame(entry3, pool.getFree(Boolean.TRUE));
343         Assert.assertSame(entry1, pool.getFree(Boolean.TRUE));
344         Assert.assertSame(null, pool.getFree(Boolean.TRUE));
345     }
346 
347     @Test(expected=IllegalStateException.class)
348     public void testReleaseInvalidEntry() throws Exception {
349         final LocalRoutePool pool = new LocalRoutePool();
350         final IOSession session = Mockito.mock(IOSession.class);
351         final LocalPoolEntry entry = new LocalPoolEntry("whatever", session);
352         pool.free(entry, true);
353     }
354 
355     @Test
356     public void testRemove() throws Exception {
357         final LocalRoutePool pool = new LocalRoutePool();
358         final IOSession session1 = Mockito.mock(IOSession.class);
359         final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
360         Mockito.when(sessionRequest1.getSession()).thenReturn(session1);
361         final BasicFuture<LocalPoolEntry> future1 = new BasicFuture<LocalPoolEntry>(null);
362         pool.addPending(sessionRequest1, future1);
363         final IOSession session2 = Mockito.mock(IOSession.class);
364         final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
365         Mockito.when(sessionRequest2.getSession()).thenReturn(session2);
366         final BasicFuture<LocalPoolEntry> future2 = new BasicFuture<LocalPoolEntry>(null);
367         pool.addPending(sessionRequest2, future2);
368         final IOSession session3 = Mockito.mock(IOSession.class);
369         final SessionRequest sessionRequest3 = Mockito.mock(SessionRequest.class);
370         Mockito.when(sessionRequest3.getSession()).thenReturn(session3);
371         final BasicFuture<LocalPoolEntry> future3 = new BasicFuture<LocalPoolEntry>(null);
372         pool.addPending(sessionRequest3, future3);
373 
374         Assert.assertEquals(3, pool.getAllocatedCount());
375         Assert.assertEquals(0, pool.getAvailableCount());
376         Assert.assertEquals(0, pool.getLeasedCount());
377         Assert.assertEquals(3, pool.getPendingCount());
378 
379         final LocalPoolEntry entry1 = pool.createEntry(sessionRequest1, session1);
380         pool.completed(sessionRequest1, entry1);
381         Assert.assertNotNull(entry1);
382         final LocalPoolEntry entry2 = pool.createEntry(sessionRequest2, session2);
383         pool.completed(sessionRequest2, entry2);
384         Assert.assertNotNull(entry2);
385         final LocalPoolEntry entry3 = pool.createEntry(sessionRequest3, session3);
386         pool.completed(sessionRequest3, entry3);
387         Assert.assertNotNull(entry3);
388 
389         Assert.assertEquals(3, pool.getAllocatedCount());
390         Assert.assertEquals(0, pool.getAvailableCount());
391         Assert.assertEquals(3, pool.getLeasedCount());
392         Assert.assertEquals(0, pool.getPendingCount());
393 
394         Assert.assertTrue(pool.remove(entry2));
395         Assert.assertFalse(pool.remove(entry2));
396 
397         Assert.assertEquals(2, pool.getAllocatedCount());
398         Assert.assertEquals(0, pool.getAvailableCount());
399         Assert.assertEquals(2, pool.getLeasedCount());
400         Assert.assertEquals(0, pool.getPendingCount());
401 
402         pool.free(entry1, true);
403         pool.free(entry3, true);
404 
405         Assert.assertEquals(2, pool.getAllocatedCount());
406         Assert.assertEquals(2, pool.getAvailableCount());
407         Assert.assertEquals(0, pool.getLeasedCount());
408         Assert.assertEquals(0, pool.getPendingCount());
409 
410         Assert.assertTrue(pool.remove(entry1));
411         Assert.assertTrue(pool.remove(entry3));
412 
413         Assert.assertEquals(0, pool.getAllocatedCount());
414         Assert.assertEquals(0, pool.getAvailableCount());
415         Assert.assertEquals(0, pool.getLeasedCount());
416         Assert.assertEquals(0, pool.getPendingCount());
417     }
418 
419     @Test(expected=IllegalArgumentException.class)
420     public void testReleaseInvalid() throws Exception {
421         final LocalRoutePool pool = new LocalRoutePool();
422         pool.free(null, true);
423     }
424 
425     @Test(expected=IllegalArgumentException.class)
426     public void testRemoveInvalid() throws Exception {
427         final LocalRoutePool pool = new LocalRoutePool();
428         pool.remove(null);
429     }
430 
431     @Test
432     public void testShutdown() throws Exception {
433         final LocalRoutePool pool = new LocalRoutePool();
434         final IOSession session1 = Mockito.mock(IOSession.class);
435         final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
436         Mockito.when(sessionRequest1.getSession()).thenReturn(session1);
437         final BasicFuture<LocalPoolEntry> future1 = new BasicFuture<LocalPoolEntry>(null);
438         pool.addPending(sessionRequest1, future1);
439         final IOSession session2 = Mockito.mock(IOSession.class);
440         final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
441         Mockito.when(sessionRequest2.getSession()).thenReturn(session2);
442         final BasicFuture<LocalPoolEntry> future2 = new BasicFuture<LocalPoolEntry>(null);
443         pool.addPending(sessionRequest2, future2);
444         final IOSession session3 = Mockito.mock(IOSession.class);
445         final SessionRequest sessionRequest3 = Mockito.mock(SessionRequest.class);
446         Mockito.when(sessionRequest3.getSession()).thenReturn(session3);
447         final BasicFuture<LocalPoolEntry> future3 = new BasicFuture<LocalPoolEntry>(null);
448         pool.addPending(sessionRequest3, future3);
449 
450         final LocalPoolEntry entry1 = pool.createEntry(sessionRequest1, session1);
451         pool.completed(sessionRequest1, entry1);
452         Assert.assertNotNull(entry1);
453         final LocalPoolEntry entry2 = pool.createEntry(sessionRequest2, session2);
454         pool.completed(sessionRequest2, entry2);
455         Assert.assertNotNull(entry2);
456 
457         pool.free(entry1, true);
458 
459         Assert.assertEquals(3, pool.getAllocatedCount());
460         Assert.assertEquals(1, pool.getAvailableCount());
461         Assert.assertEquals(1, pool.getLeasedCount());
462         Assert.assertEquals(1, pool.getPendingCount());
463 
464         pool.shutdown();
465 
466         Assert.assertEquals(0, pool.getAllocatedCount());
467         Assert.assertEquals(0, pool.getAvailableCount());
468         Assert.assertEquals(0, pool.getLeasedCount());
469         Assert.assertEquals(0, pool.getPendingCount());
470 
471         Mockito.verify(sessionRequest3).cancel();
472         Mockito.verify(session2).close();
473         Mockito.verify(session1).close();
474     }
475 
476 }