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