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.net.SocketAddress;
34 import java.net.UnknownHostException;
35 import java.util.Collections;
36 import java.util.concurrent.CancellationException;
37 import java.util.concurrent.ExecutionException;
38 import java.util.concurrent.Future;
39 import java.util.concurrent.TimeUnit;
40
41 import org.apache.http.concurrent.BasicFuture;
42 import org.apache.http.nio.reactor.ConnectingIOReactor;
43 import org.apache.http.nio.reactor.IOReactorStatus;
44 import org.apache.http.nio.reactor.IOSession;
45 import org.apache.http.nio.reactor.SessionRequest;
46 import org.apache.http.nio.reactor.SessionRequestCallback;
47 import org.apache.http.pool.PoolEntry;
48 import org.apache.http.pool.PoolStats;
49 import org.junit.Assert;
50 import org.junit.Test;
51 import org.mockito.Matchers;
52 import org.mockito.Mockito;
53
54 public class TestNIOConnPool {
55
56 static class LocalPoolEntry extends PoolEntry<String, IOSession> {
57
58 private boolean closed;
59
60 public LocalPoolEntry(final String route, final IOSession conn) {
61 super(null, route, conn);
62 }
63
64 @Override
65 public void close() {
66 if (this.closed) {
67 return;
68 }
69 this.closed = true;
70 getConnection().close();
71 }
72
73 @Override
74 public boolean isClosed() {
75 return this.closed;
76 }
77
78 }
79
80 static class LocalConnFactory implements NIOConnFactory<String, IOSession> {
81
82 @Override
83 public IOSession create(final String route, final IOSession session) throws IOException {
84 return session;
85 }
86
87 }
88
89 static class LocalAddressResolver implements SocketAddressResolver<String> {
90
91 @Override
92 public SocketAddress resolveLocalAddress(final String route) {
93 return null;
94 }
95
96 @Override
97 public SocketAddress resolveRemoteAddress(final String route) {
98 return InetSocketAddress.createUnresolved(route, 80);
99 }
100
101 }
102
103 static class LocalSessionPool extends AbstractNIOConnPool<String, IOSession, LocalPoolEntry> {
104
105 public LocalSessionPool(
106 final ConnectingIOReactor ioReactor, final int defaultMaxPerRoute, final int maxTotal) {
107 super(ioReactor, new LocalConnFactory(), new LocalAddressResolver(), defaultMaxPerRoute, maxTotal);
108 }
109
110 public LocalSessionPool(
111 final ConnectingIOReactor ioReactor,
112 final SocketAddressResolver<String> addressResolver,
113 final int defaultMaxPerRoute, final int maxTotal) {
114 super(ioReactor, new LocalConnFactory(), addressResolver, defaultMaxPerRoute, maxTotal);
115 }
116
117 @Override
118 protected LocalPoolEntry createEntry(final String route, final IOSession session) {
119 return new LocalPoolEntry(route, session);
120 }
121
122 }
123
124 @Test
125 public void testEmptyPool() throws Exception {
126 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
127 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 10);
128 final PoolStats totals = pool.getTotalStats();
129 Assert.assertEquals(0, totals.getAvailable());
130 Assert.assertEquals(0, totals.getLeased());
131 Assert.assertEquals(0, totals.getPending());
132 Assert.assertEquals(10, totals.getMax());
133 Assert.assertEquals(Collections.emptySet(), pool.getRoutes());
134 final PoolStats stats = pool.getStats("somehost");
135 Assert.assertEquals(0, stats.getAvailable());
136 Assert.assertEquals(0, stats.getLeased());
137 Assert.assertEquals(0, stats.getPending());
138 Assert.assertEquals(2, stats.getMax());
139 Assert.assertEquals("[leased: []][available: []][pending: []]", pool.toString());
140 }
141
142 @Test
143 public void testInternalLeaseRequest() throws Exception {
144 final LeaseRequest<String, IOSession, LocalPoolEntry> leaseRequest =
145 new LeaseRequest<String, IOSession, LocalPoolEntry>("somehost", null, 0, 0,
146 new BasicFuture<LocalPoolEntry>(null));
147 Assert.assertEquals("[somehost][null]", leaseRequest.toString());
148 }
149
150 @Test
151 public void testInvalidConstruction() throws Exception {
152 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
153 try {
154 new LocalSessionPool(null, 1, 1);
155 Assert.fail("IllegalArgumentException should have been thrown");
156 } catch (final IllegalArgumentException expected) {
157 }
158 try {
159 new LocalSessionPool(ioReactor, -1, 1);
160 Assert.fail("IllegalArgumentException should have been thrown");
161 } catch (final IllegalArgumentException expected) {
162 }
163 try {
164 new LocalSessionPool(ioReactor, 1, -1);
165 Assert.fail("IllegalArgumentException should have been thrown");
166 } catch (final IllegalArgumentException expected) {
167 }
168 }
169
170 @Test
171 public void testSuccessfulConnect() throws Exception {
172 final IOSession ioSession = Mockito.mock(IOSession.class);
173 final SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
174 Mockito.when(sessionRequest.getAttachment()).thenReturn("somehost");
175 Mockito.when(sessionRequest.getSession()).thenReturn(ioSession);
176 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
177 Mockito.when(ioReactor.connect(
178 Matchers.any(SocketAddress.class),
179 Matchers.any(SocketAddress.class),
180 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
181 thenReturn(sessionRequest);
182 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 10);
183 final Future<LocalPoolEntry> future = pool.lease("somehost", null, 100, TimeUnit.MILLISECONDS, null);
184 Mockito.verify(sessionRequest).setConnectTimeout(100);
185
186 PoolStats totals = pool.getTotalStats();
187 Assert.assertEquals(0, totals.getAvailable());
188 Assert.assertEquals(0, totals.getLeased());
189 Assert.assertEquals(1, totals.getPending());
190
191 pool.requestCompleted(sessionRequest);
192
193 Assert.assertTrue(future.isDone());
194 Assert.assertFalse(future.isCancelled());
195 final LocalPoolEntry entry = future.get();
196 Assert.assertNotNull(entry);
197
198 totals = pool.getTotalStats();
199 Assert.assertEquals(0, totals.getAvailable());
200 Assert.assertEquals(1, totals.getLeased());
201 Assert.assertEquals(0, totals.getPending());
202 }
203
204 @Test
205 public void testFailedConnect() throws Exception {
206 final SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
207 Mockito.when(sessionRequest.getAttachment()).thenReturn("somehost");
208 Mockito.when(sessionRequest.getException()).thenReturn(new IOException());
209 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
210 Mockito.when(ioReactor.connect(
211 Matchers.any(SocketAddress.class),
212 Matchers.any(SocketAddress.class),
213 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
214 thenReturn(sessionRequest);
215 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 10);
216 final Future<LocalPoolEntry> future = pool.lease("somehost", null);
217
218 PoolStats totals = pool.getTotalStats();
219 Assert.assertEquals(0, totals.getAvailable());
220 Assert.assertEquals(0, totals.getLeased());
221 Assert.assertEquals(1, totals.getPending());
222
223 pool.requestFailed(sessionRequest);
224
225 Assert.assertTrue(future.isDone());
226 Assert.assertFalse(future.isCancelled());
227 try {
228 future.get();
229 Assert.fail("ExecutionException should have been thrown");
230 } catch (final ExecutionException ex) {
231 Assert.assertTrue(ex.getCause() instanceof IOException);
232 }
233
234 totals = pool.getTotalStats();
235 Assert.assertEquals(0, totals.getAvailable());
236 Assert.assertEquals(0, totals.getLeased());
237 Assert.assertEquals(0, totals.getPending());
238 }
239
240 @Test
241 public void testCencelledConnect() throws Exception {
242 final IOSession ioSession = Mockito.mock(IOSession.class);
243 final SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
244 Mockito.when(sessionRequest.getAttachment()).thenReturn("somehost");
245 Mockito.when(sessionRequest.getSession()).thenReturn(ioSession);
246 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
247 Mockito.when(ioReactor.connect(
248 Matchers.any(SocketAddress.class),
249 Matchers.any(SocketAddress.class),
250 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
251 thenReturn(sessionRequest);
252 Mockito.when(ioReactor.getStatus()).thenReturn(IOReactorStatus.ACTIVE);
253 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 10);
254 final Future<LocalPoolEntry> future = pool.lease("somehost", null);
255
256 PoolStats totals = pool.getTotalStats();
257 Assert.assertEquals(0, totals.getAvailable());
258 Assert.assertEquals(0, totals.getLeased());
259 Assert.assertEquals(1, totals.getPending());
260
261 pool.requestCancelled(sessionRequest);
262
263 Assert.assertTrue(future.isDone());
264 Assert.assertTrue(future.isCancelled());
265 try {
266 future.get();
267 Assert.fail("CancellationException expected");
268 } catch (final CancellationException ignore) {
269 }
270
271 totals = pool.getTotalStats();
272 Assert.assertEquals(0, totals.getAvailable());
273 Assert.assertEquals(0, totals.getLeased());
274 Assert.assertEquals(0, totals.getPending());
275 }
276
277 @Test
278 public void testTimeoutConnect() throws Exception {
279 final IOSession ioSession = Mockito.mock(IOSession.class);
280 final SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
281 Mockito.when(sessionRequest.getAttachment()).thenReturn("somehost");
282 Mockito.when(sessionRequest.getRemoteAddress())
283 .thenReturn(new InetSocketAddress(InetAddress.getByAddress(new byte[]{127, 0, 0, 1}), 80));
284 Mockito.when(sessionRequest.getSession()).thenReturn(ioSession);
285 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
286 Mockito.when(ioReactor.connect(
287 Matchers.any(SocketAddress.class),
288 Matchers.any(SocketAddress.class),
289 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
290 thenReturn(sessionRequest);
291 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 10);
292 final Future<LocalPoolEntry> future = pool.lease("somehost", null);
293
294 PoolStats totals = pool.getTotalStats();
295 Assert.assertEquals(0, totals.getAvailable());
296 Assert.assertEquals(0, totals.getLeased());
297 Assert.assertEquals(1, totals.getPending());
298
299 pool.requestTimeout(sessionRequest);
300
301 Assert.assertTrue(future.isDone());
302 Assert.assertFalse(future.isCancelled());
303 try {
304 future.get();
305 Assert.fail("ExecutionException should have been thrown");
306 } catch (final ExecutionException ex) {
307 Assert.assertTrue(ex.getCause() instanceof ConnectException);
308 Assert.assertEquals("Timeout connecting to [/127.0.0.1:80]", ex.getCause().getMessage());
309 }
310
311 totals = pool.getTotalStats();
312 Assert.assertEquals(0, totals.getAvailable());
313 Assert.assertEquals(0, totals.getLeased());
314 Assert.assertEquals(0, totals.getPending());
315 }
316
317 @Test
318 public void testConnectUnknownHost() throws Exception {
319 final SessionRequest sessionRequest = Mockito.mock(SessionRequest.class);
320 Mockito.when(sessionRequest.getAttachment()).thenReturn("somehost");
321 Mockito.when(sessionRequest.getException()).thenReturn(new IOException());
322 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
323 final SocketAddressResolver<String> addressResolver = Mockito.mock(SocketAddressResolver.class);
324 Mockito.when(addressResolver.resolveRemoteAddress("somehost")).thenThrow(new UnknownHostException());
325 final LocalSessionPool pool = new LocalSessionPool(ioReactor, addressResolver, 2, 10);
326 final Future<LocalPoolEntry> future = pool.lease("somehost", null);
327
328 Assert.assertTrue(future.isDone());
329 Assert.assertFalse(future.isCancelled());
330 try {
331 future.get();
332 Assert.fail("ExecutionException should have been thrown");
333 } catch (final ExecutionException ex) {
334 Assert.assertTrue(ex.getCause() instanceof UnknownHostException);
335 }
336 }
337
338 @Test
339 public void testLeaseRelease() throws Exception {
340 final IOSession ioSession1 = Mockito.mock(IOSession.class);
341 final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
342 Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
343 Mockito.when(sessionRequest1.getSession()).thenReturn(ioSession1);
344
345 final IOSession ioSession2 = Mockito.mock(IOSession.class);
346 final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
347 Mockito.when(sessionRequest2.getAttachment()).thenReturn("otherhost");
348 Mockito.when(sessionRequest2.getSession()).thenReturn(ioSession2);
349
350 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
351 Mockito.when(ioReactor.connect(
352 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
353 Matchers.any(SocketAddress.class),
354 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
355 thenReturn(sessionRequest1);
356 Mockito.when(ioReactor.connect(
357 Matchers.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
358 Matchers.any(SocketAddress.class),
359 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
360 thenReturn(sessionRequest2);
361
362 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 10);
363 final Future<LocalPoolEntry> future1 = pool.lease("somehost", null);
364 pool.requestCompleted(sessionRequest1);
365 final Future<LocalPoolEntry> future2 = pool.lease("somehost", null);
366 pool.requestCompleted(sessionRequest1);
367 final Future<LocalPoolEntry> future3 = pool.lease("otherhost", null);
368 pool.requestCompleted(sessionRequest2);
369
370 final LocalPoolEntry entry1 = future1.get();
371 Assert.assertNotNull(entry1);
372 final LocalPoolEntry entry2 = future2.get();
373 Assert.assertNotNull(entry2);
374 final LocalPoolEntry entry3 = future3.get();
375 Assert.assertNotNull(entry3);
376
377 pool.release(entry1, true);
378 pool.release(entry2, true);
379 pool.release(entry3, false);
380 Mockito.verify(ioSession1, Mockito.never()).close();
381 Mockito.verify(ioSession2, Mockito.times(1)).close();
382
383 final PoolStats totals = pool.getTotalStats();
384 Assert.assertEquals(2, totals.getAvailable());
385 Assert.assertEquals(0, totals.getLeased());
386 Assert.assertEquals(0, totals.getPending());
387 }
388
389 @Test
390 public void testLeaseIllegal() throws Exception {
391 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
392 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 10);
393 try {
394 pool.lease(null, null, 0, TimeUnit.MILLISECONDS, null);
395 Assert.fail("IllegalArgumentException should have been thrown");
396 } catch (final IllegalArgumentException expected) {
397 }
398 try {
399 pool.lease("somehost", null, 0, null, null);
400 Assert.fail("IllegalArgumentException should have been thrown");
401 } catch (final IllegalArgumentException expected) {
402 }
403 }
404
405 @Test
406 public void testReleaseUnknownEntry() throws Exception {
407 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
408 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 2);
409 pool.release(new LocalPoolEntry("somehost", Mockito.mock(IOSession.class)), true);
410 }
411
412 @Test
413 public void testMaxLimits() throws Exception {
414 final IOSession ioSession1 = Mockito.mock(IOSession.class);
415 final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
416 Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
417 Mockito.when(sessionRequest1.getSession()).thenReturn(ioSession1);
418
419 final IOSession ioSession2 = Mockito.mock(IOSession.class);
420 final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
421 Mockito.when(sessionRequest2.getAttachment()).thenReturn("otherhost");
422 Mockito.when(sessionRequest2.getSession()).thenReturn(ioSession2);
423
424 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
425 Mockito.when(ioReactor.connect(
426 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
427 Matchers.any(SocketAddress.class),
428 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
429 thenReturn(sessionRequest1);
430 Mockito.when(ioReactor.connect(
431 Matchers.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
432 Matchers.any(SocketAddress.class),
433 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
434 thenReturn(sessionRequest2);
435
436 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 10);
437 pool.setMaxPerRoute("somehost", 2);
438 pool.setMaxPerRoute("otherhost", 1);
439 pool.setMaxTotal(3);
440
441 final Future<LocalPoolEntry> future1 = pool.lease("somehost", null);
442 pool.requestCompleted(sessionRequest1);
443 final Future<LocalPoolEntry> future2 = pool.lease("somehost", null);
444 pool.requestCompleted(sessionRequest1);
445 final Future<LocalPoolEntry> future3 = pool.lease("otherhost", null);
446 pool.requestCompleted(sessionRequest2);
447
448 final LocalPoolEntry entry1 = future1.get();
449 Assert.assertNotNull(entry1);
450 final LocalPoolEntry entry2 = future2.get();
451 Assert.assertNotNull(entry2);
452 final LocalPoolEntry entry3 = future3.get();
453 Assert.assertNotNull(entry3);
454
455 pool.release(entry1, true);
456 pool.release(entry2, true);
457 pool.release(entry3, true);
458
459 final PoolStats totals = pool.getTotalStats();
460 Assert.assertEquals(3, totals.getAvailable());
461 Assert.assertEquals(0, totals.getLeased());
462 Assert.assertEquals(0, totals.getPending());
463
464 final Future<LocalPoolEntry> future4 = pool.lease("somehost", null);
465 final Future<LocalPoolEntry> future5 = pool.lease("somehost", null);
466 final Future<LocalPoolEntry> future6 = pool.lease("otherhost", null);
467 final Future<LocalPoolEntry> future7 = pool.lease("somehost", null);
468 final Future<LocalPoolEntry> future8 = pool.lease("somehost", null);
469 final Future<LocalPoolEntry> future9 = pool.lease("otherhost", null);
470
471 Assert.assertTrue(future4.isDone());
472 final LocalPoolEntry entry4 = future4.get();
473 Assert.assertNotNull(entry4);
474 Assert.assertTrue(future5.isDone());
475 final LocalPoolEntry entry5 = future5.get();
476 Assert.assertNotNull(entry5);
477 Assert.assertTrue(future6.isDone());
478 final LocalPoolEntry entry6 = future6.get();
479 Assert.assertNotNull(entry6);
480 Assert.assertFalse(future7.isDone());
481 Assert.assertFalse(future8.isDone());
482 Assert.assertFalse(future9.isDone());
483
484 Mockito.verify(ioReactor, Mockito.times(3)).connect(
485 Matchers.any(SocketAddress.class), Matchers.any(SocketAddress.class),
486 Matchers.any(), Matchers.any(SessionRequestCallback.class));
487
488 pool.release(entry4, true);
489 pool.release(entry5, false);
490 pool.release(entry6, true);
491
492 Assert.assertTrue(future7.isDone());
493 Assert.assertFalse(future8.isDone());
494 Assert.assertTrue(future9.isDone());
495
496 Mockito.verify(ioReactor, Mockito.times(4)).connect(
497 Matchers.any(SocketAddress.class), Matchers.any(SocketAddress.class),
498 Matchers.any(), Matchers.any(SessionRequestCallback.class));
499 }
500
501 @Test
502 public void testConnectionRedistributionOnTotalMaxLimit() throws Exception {
503 final IOSession ioSession1 = Mockito.mock(IOSession.class);
504 final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
505 Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
506 Mockito.when(sessionRequest1.getSession()).thenReturn(ioSession1);
507
508 final IOSession ioSession2 = Mockito.mock(IOSession.class);
509 final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
510 Mockito.when(sessionRequest2.getAttachment()).thenReturn("somehost");
511 Mockito.when(sessionRequest2.getSession()).thenReturn(ioSession2);
512
513 final IOSession ioSession3 = Mockito.mock(IOSession.class);
514 final SessionRequest sessionRequest3 = Mockito.mock(SessionRequest.class);
515 Mockito.when(sessionRequest3.getAttachment()).thenReturn("otherhost");
516 Mockito.when(sessionRequest3.getSession()).thenReturn(ioSession3);
517
518 final IOSession ioSession4 = Mockito.mock(IOSession.class);
519 final SessionRequest sessionRequest4 = Mockito.mock(SessionRequest.class);
520 Mockito.when(sessionRequest4.getAttachment()).thenReturn("otherhost");
521 Mockito.when(sessionRequest4.getSession()).thenReturn(ioSession4);
522
523 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
524 Mockito.when(ioReactor.connect(
525 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
526 Matchers.any(SocketAddress.class),
527 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
528 thenReturn(sessionRequest1, sessionRequest2, sessionRequest1);
529 Mockito.when(ioReactor.connect(
530 Matchers.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
531 Matchers.any(SocketAddress.class),
532 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
533 thenReturn(sessionRequest3, sessionRequest4, sessionRequest3);
534
535 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 10);
536 pool.setMaxPerRoute("somehost", 2);
537 pool.setMaxPerRoute("otherhost", 2);
538 pool.setMaxTotal(2);
539
540 final Future<LocalPoolEntry> future1 = pool.lease("somehost", null);
541 final Future<LocalPoolEntry> future2 = pool.lease("somehost", null);
542 final Future<LocalPoolEntry> future3 = pool.lease("otherhost", null);
543 final Future<LocalPoolEntry> future4 = pool.lease("otherhost", null);
544
545 Mockito.verify(ioReactor, Mockito.times(2)).connect(
546 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
547 Matchers.any(SocketAddress.class),
548 Matchers.any(), Matchers.any(SessionRequestCallback.class));
549
550 Mockito.verify(ioReactor, Mockito.never()).connect(
551 Matchers.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
552 Matchers.any(SocketAddress.class),
553 Matchers.any(), Matchers.any(SessionRequestCallback.class));
554
555 pool.requestCompleted(sessionRequest1);
556 pool.requestCompleted(sessionRequest2);
557
558 Assert.assertTrue(future1.isDone());
559 final LocalPoolEntry entry1 = future1.get();
560 Assert.assertNotNull(entry1);
561 Assert.assertTrue(future2.isDone());
562 final LocalPoolEntry entry2 = future2.get();
563 Assert.assertNotNull(entry2);
564
565 Assert.assertFalse(future3.isDone());
566 Assert.assertFalse(future4.isDone());
567
568 PoolStats totals = pool.getTotalStats();
569 Assert.assertEquals(0, totals.getAvailable());
570 Assert.assertEquals(2, totals.getLeased());
571 Assert.assertEquals(0, totals.getPending());
572
573 pool.release(entry1, true);
574 pool.release(entry2, true);
575
576 Mockito.verify(ioReactor, Mockito.times(2)).connect(
577 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
578 Matchers.any(SocketAddress.class),
579 Matchers.any(), Matchers.any(SessionRequestCallback.class));
580
581 Mockito.verify(ioReactor, Mockito.times(2)).connect(
582 Matchers.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
583 Matchers.any(SocketAddress.class),
584 Matchers.any(), Matchers.any(SessionRequestCallback.class));
585
586 pool.requestCompleted(sessionRequest3);
587 pool.requestCompleted(sessionRequest4);
588
589 Assert.assertTrue(future3.isDone());
590 final LocalPoolEntry entry3 = future3.get();
591 Assert.assertNotNull(entry3);
592 Assert.assertTrue(future4.isDone());
593 final LocalPoolEntry entry4 = future4.get();
594 Assert.assertNotNull(entry4);
595
596 totals = pool.getTotalStats();
597 Assert.assertEquals(0, totals.getAvailable());
598 Assert.assertEquals(2, totals.getLeased());
599 Assert.assertEquals(0, totals.getPending());
600
601 final Future<LocalPoolEntry> future5 = pool.lease("somehost", null);
602 final Future<LocalPoolEntry> future6 = pool.lease("otherhost", null);
603
604 Mockito.verify(ioReactor, Mockito.times(2)).connect(
605 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
606 Matchers.any(SocketAddress.class),
607 Matchers.any(), Matchers.any(SessionRequestCallback.class));
608
609 Mockito.verify(ioReactor, Mockito.times(2)).connect(
610 Matchers.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
611 Matchers.any(SocketAddress.class),
612 Matchers.any(), Matchers.any(SessionRequestCallback.class));
613
614 pool.release(entry3, true);
615 pool.release(entry4, true);
616
617 Mockito.verify(ioReactor, Mockito.times(3)).connect(
618 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
619 Matchers.any(SocketAddress.class),
620 Matchers.any(), Matchers.any(SessionRequestCallback.class));
621
622 Mockito.verify(ioReactor, Mockito.times(2)).connect(
623 Matchers.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
624 Matchers.any(SocketAddress.class),
625 Matchers.any(), Matchers.any(SessionRequestCallback.class));
626
627 pool.requestCompleted(sessionRequest1);
628
629 Assert.assertTrue(future5.isDone());
630 final LocalPoolEntry entry5 = future5.get();
631 Assert.assertNotNull(entry5);
632 Assert.assertTrue(future6.isDone());
633 final LocalPoolEntry entry6 = future6.get();
634 Assert.assertNotNull(entry6);
635
636 totals = pool.getTotalStats();
637 Assert.assertEquals(0, totals.getAvailable());
638 Assert.assertEquals(2, totals.getLeased());
639 Assert.assertEquals(0, totals.getPending());
640
641 pool.release(entry5, true);
642 pool.release(entry6, true);
643
644 Mockito.verify(ioReactor, Mockito.times(3)).connect(
645 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
646 Matchers.any(SocketAddress.class),
647 Matchers.any(), Matchers.any(SessionRequestCallback.class));
648
649 Mockito.verify(ioReactor, Mockito.times(2)).connect(
650 Matchers.eq(InetSocketAddress.createUnresolved("otherhost", 80)),
651 Matchers.any(SocketAddress.class),
652 Matchers.any(), Matchers.any(SessionRequestCallback.class));
653
654 totals = pool.getTotalStats();
655 Assert.assertEquals(2, totals.getAvailable());
656 Assert.assertEquals(0, totals.getLeased());
657 Assert.assertEquals(0, totals.getPending());
658 }
659
660 @Test
661 public void testStatefulConnectionRedistributionOnPerRouteMaxLimit() throws Exception {
662 final IOSession ioSession1 = Mockito.mock(IOSession.class);
663 final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
664 Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
665 Mockito.when(sessionRequest1.getSession()).thenReturn(ioSession1);
666
667 final IOSession ioSession2 = Mockito.mock(IOSession.class);
668 final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
669 Mockito.when(sessionRequest2.getAttachment()).thenReturn("somehost");
670 Mockito.when(sessionRequest2.getSession()).thenReturn(ioSession2);
671
672 final IOSession ioSession3 = Mockito.mock(IOSession.class);
673 final SessionRequest sessionRequest3 = Mockito.mock(SessionRequest.class);
674 Mockito.when(sessionRequest3.getAttachment()).thenReturn("somehost");
675 Mockito.when(sessionRequest3.getSession()).thenReturn(ioSession3);
676
677 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
678 Mockito.when(ioReactor.connect(
679 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
680 Matchers.any(SocketAddress.class),
681 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
682 thenReturn(sessionRequest1, sessionRequest2, sessionRequest3);
683
684 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 10);
685 pool.setMaxPerRoute("somehost", 2);
686 pool.setMaxTotal(2);
687
688 final Future<LocalPoolEntry> future1 = pool.lease("somehost", null);
689 final Future<LocalPoolEntry> future2 = pool.lease("somehost", null);
690
691 Mockito.verify(ioReactor, Mockito.times(2)).connect(
692 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
693 Matchers.any(SocketAddress.class),
694 Matchers.any(), Matchers.any(SessionRequestCallback.class));
695
696 pool.requestCompleted(sessionRequest1);
697 pool.requestCompleted(sessionRequest2);
698
699 Assert.assertTrue(future1.isDone());
700 final LocalPoolEntry entry1 = future1.get();
701 Assert.assertNotNull(entry1);
702 Assert.assertTrue(future2.isDone());
703 final LocalPoolEntry entry2 = future2.get();
704 Assert.assertNotNull(entry2);
705
706 PoolStats totals = pool.getTotalStats();
707 Assert.assertEquals(0, totals.getAvailable());
708 Assert.assertEquals(2, totals.getLeased());
709 Assert.assertEquals(0, totals.getPending());
710
711 entry1.setState("some-stuff");
712 pool.release(entry1, true);
713 entry2.setState("some-stuff");
714 pool.release(entry2, true);
715
716 final Future<LocalPoolEntry> future3 = pool.lease("somehost", "some-stuff");
717 final Future<LocalPoolEntry> future4 = pool.lease("somehost", "some-stuff");
718
719 Assert.assertTrue(future1.isDone());
720 final LocalPoolEntry entry3 = future3.get();
721 Assert.assertNotNull(entry3);
722 Assert.assertTrue(future4.isDone());
723 final LocalPoolEntry entry4 = future4.get();
724 Assert.assertNotNull(entry4);
725
726 Mockito.verify(ioReactor, Mockito.times(2)).connect(
727 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
728 Matchers.any(SocketAddress.class),
729 Matchers.any(), Matchers.any(SessionRequestCallback.class));
730
731 pool.release(entry3, true);
732 pool.release(entry4, true);
733
734 totals = pool.getTotalStats();
735 Assert.assertEquals(2, totals.getAvailable());
736 Assert.assertEquals(0, totals.getLeased());
737 Assert.assertEquals(0, totals.getPending());
738
739 final Future<LocalPoolEntry> future5 = pool.lease("somehost", "some-other-stuff");
740
741 Assert.assertFalse(future5.isDone());
742
743 Mockito.verify(ioReactor, Mockito.times(3)).connect(
744 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
745 Matchers.any(SocketAddress.class),
746 Matchers.any(), Matchers.any(SessionRequestCallback.class));
747
748 Mockito.verify(ioSession2).close();
749 Mockito.verify(ioSession1, Mockito.never()).close();
750
751 totals = pool.getTotalStats();
752 Assert.assertEquals(1, totals.getAvailable());
753 Assert.assertEquals(0, totals.getLeased());
754 Assert.assertEquals(1, totals.getPending());
755 }
756
757 @Test
758 public void testCreateNewIfExpired() throws Exception {
759 final IOSession ioSession1 = Mockito.mock(IOSession.class);
760 Mockito.when(ioSession1.isClosed()).thenReturn(Boolean.TRUE);
761 final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
762 Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
763 Mockito.when(sessionRequest1.getSession()).thenReturn(ioSession1);
764
765 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
766 Mockito.when(ioReactor.connect(
767 Matchers.eq(InetSocketAddress.createUnresolved("somehost", 80)),
768 Matchers.any(SocketAddress.class),
769 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
770 thenReturn(sessionRequest1);
771
772 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 2);
773
774 final Future<LocalPoolEntry> future1 = pool.lease("somehost", null);
775
776 Mockito.verify(ioReactor, Mockito.times(1)).connect(
777 Matchers.any(SocketAddress.class), Matchers.any(SocketAddress.class),
778 Matchers.any(), Matchers.any(SessionRequestCallback.class));
779
780 pool.requestCompleted(sessionRequest1);
781
782 Assert.assertTrue(future1.isDone());
783 final LocalPoolEntry entry1 = future1.get();
784 Assert.assertNotNull(entry1);
785
786 entry1.updateExpiry(1, TimeUnit.MILLISECONDS);
787 pool.release(entry1, true);
788
789 Thread.sleep(200L);
790
791 final Future<LocalPoolEntry> future2 = pool.lease("somehost", null);
792
793 Assert.assertFalse(future2.isDone());
794
795 Mockito.verify(ioSession1).close();
796 Mockito.verify(ioReactor, Mockito.times(2)).connect(
797 Matchers.any(SocketAddress.class), Matchers.any(SocketAddress.class),
798 Matchers.any(), Matchers.any(SessionRequestCallback.class));
799
800 final PoolStats totals = pool.getTotalStats();
801 Assert.assertEquals(0, totals.getAvailable());
802 Assert.assertEquals(0, totals.getLeased());
803 Assert.assertEquals(1, totals.getPending());
804 Assert.assertEquals(Collections.singleton("somehost"), pool.getRoutes());
805 final PoolStats stats = pool.getStats("somehost");
806 Assert.assertEquals(0, stats.getAvailable());
807 Assert.assertEquals(0, stats.getLeased());
808 Assert.assertEquals(1, stats.getPending());
809 }
810
811 @Test
812 public void testCloseExpired() throws Exception {
813 final IOSession ioSession1 = Mockito.mock(IOSession.class);
814 Mockito.when(ioSession1.isClosed()).thenReturn(Boolean.TRUE);
815 final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
816 Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
817 Mockito.when(sessionRequest1.getSession()).thenReturn(ioSession1);
818
819 final IOSession ioSession2 = Mockito.mock(IOSession.class);
820 final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
821 Mockito.when(sessionRequest2.getAttachment()).thenReturn("somehost");
822 Mockito.when(sessionRequest2.getSession()).thenReturn(ioSession2);
823
824 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
825 Mockito.when(ioReactor.connect(
826 Matchers.any(SocketAddress.class), Matchers.any(SocketAddress.class),
827 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
828 thenReturn(sessionRequest1, sessionRequest2);
829
830 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 2);
831
832 final Future<LocalPoolEntry> future1 = pool.lease("somehost", null);
833 final Future<LocalPoolEntry> future2 = pool.lease("somehost", null);
834
835 pool.requestCompleted(sessionRequest1);
836 pool.requestCompleted(sessionRequest2);
837
838 Assert.assertTrue(future1.isDone());
839 final LocalPoolEntry entry1 = future1.get();
840 Assert.assertNotNull(entry1);
841 Assert.assertTrue(future2.isDone());
842 final LocalPoolEntry entry2 = future2.get();
843 Assert.assertNotNull(entry2);
844
845 entry1.updateExpiry(1, TimeUnit.MILLISECONDS);
846 pool.release(entry1, true);
847
848 Thread.sleep(200);
849
850 entry2.updateExpiry(1000, TimeUnit.SECONDS);
851 pool.release(entry2, true);
852
853 pool.closeExpired();
854
855 Mockito.verify(ioSession1).close();
856 Mockito.verify(ioSession2, Mockito.never()).close();
857
858 final PoolStats totals = pool.getTotalStats();
859 Assert.assertEquals(1, totals.getAvailable());
860 Assert.assertEquals(0, totals.getLeased());
861 Assert.assertEquals(0, totals.getPending());
862 final PoolStats stats = pool.getStats("somehost");
863 Assert.assertEquals(1, stats.getAvailable());
864 Assert.assertEquals(0, stats.getLeased());
865 Assert.assertEquals(0, stats.getPending());
866 }
867
868 @Test
869 public void testCloseIdle() throws Exception {
870 final IOSession ioSession1 = Mockito.mock(IOSession.class);
871 final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
872 Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
873 Mockito.when(sessionRequest1.getSession()).thenReturn(ioSession1);
874
875 final IOSession ioSession2 = Mockito.mock(IOSession.class);
876 final SessionRequest sessionRequest2 = Mockito.mock(SessionRequest.class);
877 Mockito.when(sessionRequest2.getAttachment()).thenReturn("somehost");
878 Mockito.when(sessionRequest2.getSession()).thenReturn(ioSession2);
879
880 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
881 Mockito.when(ioReactor.connect(
882 Matchers.any(SocketAddress.class), Matchers.any(SocketAddress.class),
883 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
884 thenReturn(sessionRequest1, sessionRequest2);
885
886 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 2);
887
888 final Future<LocalPoolEntry> future1 = pool.lease("somehost", null);
889 final Future<LocalPoolEntry> future2 = pool.lease("somehost", null);
890
891 pool.requestCompleted(sessionRequest1);
892 pool.requestCompleted(sessionRequest2);
893
894 Assert.assertTrue(future1.isDone());
895 final LocalPoolEntry entry1 = future1.get();
896 Assert.assertNotNull(entry1);
897 Assert.assertTrue(future2.isDone());
898 final LocalPoolEntry entry2 = future2.get();
899 Assert.assertNotNull(entry2);
900
901 entry1.updateExpiry(0, TimeUnit.MILLISECONDS);
902 pool.release(entry1, true);
903
904 Thread.sleep(200L);
905
906 entry2.updateExpiry(0, TimeUnit.MILLISECONDS);
907 pool.release(entry2, true);
908
909 pool.closeIdle(50, TimeUnit.MILLISECONDS);
910
911 Mockito.verify(ioSession1).close();
912 Mockito.verify(ioSession2, Mockito.never()).close();
913
914 PoolStats totals = pool.getTotalStats();
915 Assert.assertEquals(1, totals.getAvailable());
916 Assert.assertEquals(0, totals.getLeased());
917 Assert.assertEquals(0, totals.getPending());
918 PoolStats stats = pool.getStats("somehost");
919 Assert.assertEquals(1, stats.getAvailable());
920 Assert.assertEquals(0, stats.getLeased());
921 Assert.assertEquals(0, stats.getPending());
922
923 pool.closeIdle(-1, TimeUnit.MILLISECONDS);
924
925 Mockito.verify(ioSession2).close();
926
927 totals = pool.getTotalStats();
928 Assert.assertEquals(0, totals.getAvailable());
929 Assert.assertEquals(0, totals.getLeased());
930 Assert.assertEquals(0, totals.getPending());
931 stats = pool.getStats("somehost");
932 Assert.assertEquals(0, stats.getAvailable());
933 Assert.assertEquals(0, stats.getLeased());
934 Assert.assertEquals(0, stats.getPending());
935 }
936
937 @Test
938 public void testLeaseRequestTimeout() throws Exception {
939 final IOSession ioSession1 = Mockito.mock(IOSession.class);
940 Mockito.when(ioSession1.isClosed()).thenReturn(Boolean.TRUE);
941 final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
942 Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
943 Mockito.when(sessionRequest1.getSession()).thenReturn(ioSession1);
944
945 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
946 Mockito.when(ioReactor.connect(
947 Matchers.any(SocketAddress.class), Matchers.any(SocketAddress.class),
948 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
949 thenReturn(sessionRequest1);
950
951 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 1, 1);
952
953 final Future<LocalPoolEntry> future1 = pool.lease("somehost", null, 0, TimeUnit.MILLISECONDS, null);
954 final Future<LocalPoolEntry> future2 = pool.lease("somehost", null, 0, TimeUnit.MILLISECONDS, null);
955 final Future<LocalPoolEntry> future3 = pool.lease("somehost", null, 10, TimeUnit.MILLISECONDS, null);
956
957 pool.requestCompleted(sessionRequest1);
958
959 Assert.assertTrue(future1.isDone());
960 final LocalPoolEntry entry1 = future1.get();
961 Assert.assertNotNull(entry1);
962 Assert.assertFalse(future2.isDone());
963 Assert.assertFalse(future3.isDone());
964
965 Thread.sleep(100);
966
967 pool.validatePendingRequests();
968
969 Assert.assertFalse(future2.isDone());
970 Assert.assertTrue(future3.isDone());
971 }
972
973 @Test(expected=IllegalArgumentException.class)
974 public void testCloseIdleInvalid() throws Exception {
975 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
976 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 2);
977 pool.closeIdle(50, null);
978 }
979
980 @Test(expected=IllegalArgumentException.class)
981 public void testGetStatsInvalid() throws Exception {
982 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
983 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 2);
984 pool.getStats(null);
985 }
986
987 @Test
988 public void testSetMaxInvalid() throws Exception {
989 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
990 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 2);
991 try {
992 pool.setMaxTotal(-1);
993 Assert.fail("IllegalArgumentException should have been thrown");
994 } catch (final IllegalArgumentException expected) {
995 }
996 try {
997 pool.setMaxPerRoute(null, 1);
998 Assert.fail("IllegalArgumentException should have been thrown");
999 } catch (final IllegalArgumentException expected) {
1000 }
1001 try {
1002 pool.setDefaultMaxPerRoute(-1);
1003 Assert.fail("IllegalArgumentException should have been thrown");
1004 } catch (final IllegalArgumentException expected) {
1005 }
1006 }
1007
1008 @Test
1009 public void testSetMaxPerRoute() throws Exception {
1010 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
1011 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 2);
1012 pool.setMaxPerRoute("somehost", 1);
1013 Assert.assertEquals(1, pool.getMaxPerRoute("somehost"));
1014 pool.setMaxPerRoute("somehost", 0);
1015 Assert.assertEquals(0, pool.getMaxPerRoute("somehost"));
1016 pool.setMaxPerRoute("somehost", -1);
1017 Assert.assertEquals(2, pool.getMaxPerRoute("somehost"));
1018 }
1019
1020 @Test
1021 public void testShutdown() throws Exception {
1022 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
1023 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 2, 2);
1024 pool.shutdown(1000);
1025 Mockito.verify(ioReactor, Mockito.times(1)).shutdown(1000);
1026 pool.shutdown(1000);
1027 Mockito.verify(ioReactor, Mockito.times(1)).shutdown(1000);
1028 try {
1029 pool.lease("somehost", null);
1030 Assert.fail("IllegalStateException should have been thrown");
1031 } catch (final IllegalStateException expected) {
1032 }
1033
1034 pool.release(new LocalPoolEntry("somehost", Mockito.mock(IOSession.class)), true);
1035 pool.requestCompleted(Mockito.mock(SessionRequest.class));
1036 pool.requestFailed(Mockito.mock(SessionRequest.class));
1037 pool.requestCancelled(Mockito.mock(SessionRequest.class));
1038 pool.requestTimeout(Mockito.mock(SessionRequest.class));
1039 }
1040
1041 @Test
1042 public void testLeaseRequestCanceled() throws Exception {
1043 final IOSession ioSession1 = Mockito.mock(IOSession.class);
1044 Mockito.when(ioSession1.isClosed()).thenReturn(Boolean.TRUE);
1045 final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
1046 Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
1047 Mockito.when(sessionRequest1.getSession()).thenReturn(ioSession1);
1048
1049 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
1050 Mockito.when(ioReactor.connect(
1051 Matchers.any(SocketAddress.class), Matchers.any(SocketAddress.class),
1052 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
1053 thenReturn(sessionRequest1);
1054 Mockito.when(ioReactor.getStatus()).thenReturn(IOReactorStatus.ACTIVE);
1055
1056 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 1, 1);
1057
1058 final Future<LocalPoolEntry> future1 = pool.lease("somehost", null, 0, TimeUnit.MILLISECONDS, null);
1059 future1.cancel(true);
1060
1061 pool.requestCompleted(sessionRequest1);
1062
1063 Assert.assertTrue(future1.isDone());
1064 try {
1065 future1.get();
1066 Assert.fail("CancellationException expected");
1067 } catch (final CancellationException ignore) {
1068 }
1069
1070 final PoolStats totals = pool.getTotalStats();
1071 Assert.assertEquals(1, totals.getAvailable());
1072 Assert.assertEquals(0, totals.getLeased());
1073 }
1074
1075 @Test
1076 public void testLeaseRequestCanceledWhileConnecting() throws Exception {
1077 final IOSession ioSession1 = Mockito.mock(IOSession.class);
1078 Mockito.when(ioSession1.isClosed()).thenReturn(Boolean.TRUE);
1079 final SessionRequest sessionRequest1 = Mockito.mock(SessionRequest.class);
1080 Mockito.when(sessionRequest1.getAttachment()).thenReturn("somehost");
1081 Mockito.when(sessionRequest1.getSession()).thenReturn(ioSession1);
1082
1083 final ConnectingIOReactor ioReactor = Mockito.mock(ConnectingIOReactor.class);
1084 Mockito.when(ioReactor.connect(
1085 Matchers.any(SocketAddress.class), Matchers.any(SocketAddress.class),
1086 Matchers.any(), Matchers.any(SessionRequestCallback.class))).
1087 thenReturn(sessionRequest1);
1088 Mockito.when(ioReactor.getStatus()).thenReturn(IOReactorStatus.ACTIVE);
1089
1090 final LocalSessionPool pool = new LocalSessionPool(ioReactor, 1, 1);
1091
1092 final Future<LocalPoolEntry> future1 = pool.lease("somehost", null, 0, TimeUnit.MILLISECONDS, null);
1093
1094 pool.requestCompleted(sessionRequest1);
1095
1096 Assert.assertTrue(future1.isDone());
1097 final LocalPoolEntry entry1 = future1.get();
1098 Assert.assertNotNull(entry1);
1099
1100 final Future<LocalPoolEntry> future2 = pool.lease("somehost", null, 0, TimeUnit.MILLISECONDS, null);
1101 future2.cancel(true);
1102
1103 pool.release(entry1, true);
1104
1105 final PoolStats totals = pool.getTotalStats();
1106 Assert.assertEquals(1, totals.getAvailable());
1107 Assert.assertEquals(0, totals.getLeased());
1108 }
1109
1110 }