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.hc.core5.pool;
28
29 import java.util.Collections;
30 import java.util.concurrent.CancellationException;
31 import java.util.concurrent.CountDownLatch;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.Future;
34 import java.util.concurrent.TimeUnit;
35
36 import org.apache.hc.core5.http.HttpConnection;
37 import org.apache.hc.core5.io.CloseMode;
38 import org.apache.hc.core5.util.DeadlineTimeoutException;
39 import org.apache.hc.core5.util.TimeValue;
40 import org.apache.hc.core5.util.Timeout;
41 import org.junit.jupiter.api.Assertions;
42 import org.junit.jupiter.api.Test;
43 import org.mockito.ArgumentMatchers;
44 import org.mockito.Mockito;
45
46 public class TestStrictConnPool {
47
48 @Test
49 public void testEmptyPool() throws Exception {
50 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 10)) {
51 final PoolStats totals = pool.getTotalStats();
52 Assertions.assertEquals(0, totals.getAvailable());
53 Assertions.assertEquals(0, totals.getLeased());
54 Assertions.assertEquals(0, totals.getPending());
55 Assertions.assertEquals(10, totals.getMax());
56 Assertions.assertEquals(Collections.emptySet(), pool.getRoutes());
57 final PoolStats stats = pool.getStats("somehost");
58 Assertions.assertEquals(0, stats.getAvailable());
59 Assertions.assertEquals(0, stats.getLeased());
60 Assertions.assertEquals(0, stats.getPending());
61 Assertions.assertEquals(2, stats.getMax());
62 Assertions.assertEquals("[leased: 0][available: 0][pending: 0]", pool.toString());
63 }
64 }
65
66 @Test
67 public void testInvalidConstruction() throws Exception {
68 Assertions.assertThrows(IllegalArgumentException.class, () ->
69 new StrictConnPool<String, HttpConnection>(-1, 1));
70 Assertions.assertThrows(IllegalArgumentException.class, () ->
71 new StrictConnPool<String, HttpConnection>(1, -1));
72 }
73
74 @Test
75 public void testLeaseRelease() throws Exception {
76 final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
77 final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
78 final HttpConnection conn3 = Mockito.mock(HttpConnection.class);
79
80 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 10)) {
81 final Future<PoolEntry<String, HttpConnection>> future1 = pool.lease("somehost", null);
82 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null);
83 final Future<PoolEntry<String, HttpConnection>> future3 = pool.lease("otherhost", null);
84
85 final PoolEntry<String, HttpConnection> entry1 = future1.get();
86 Assertions.assertNotNull(entry1);
87 entry1.assignConnection(conn1);
88 final PoolEntry<String, HttpConnection> entry2 = future2.get();
89 Assertions.assertNotNull(entry2);
90 entry2.assignConnection(conn2);
91 final PoolEntry<String, HttpConnection> entry3 = future3.get();
92 Assertions.assertNotNull(entry3);
93 entry3.assignConnection(conn3);
94
95 pool.release(entry1, true);
96 pool.release(entry2, true);
97 pool.release(entry3, false);
98 Mockito.verify(conn1, Mockito.never()).close(ArgumentMatchers.any());
99 Mockito.verify(conn2, Mockito.never()).close(ArgumentMatchers.any());
100 Mockito.verify(conn3, Mockito.times(1)).close(CloseMode.GRACEFUL);
101
102 final PoolStats totals = pool.getTotalStats();
103 Assertions.assertEquals(2, totals.getAvailable());
104 Assertions.assertEquals(0, totals.getLeased());
105 Assertions.assertEquals(0, totals.getPending());
106 }
107 }
108
109 @Test
110 public void testLeaseInvalid() throws Exception {
111 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 10)) {
112 Assertions.assertThrows(NullPointerException.class, () ->
113 pool.lease(null, null, Timeout.ZERO_MILLISECONDS, null));
114 Assertions.assertThrows(NullPointerException.class, () ->
115 pool.lease("somehost", null, null, null));
116 }
117 }
118
119 @Test
120 public void testReleaseUnknownEntry() throws Exception {
121 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 2)) {
122 Assertions.assertThrows(IllegalStateException.class, () ->
123 pool.release(new PoolEntry<>("somehost"), true));
124 }
125 }
126
127 @Test
128 public void testMaxLimits() throws Exception {
129 final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
130 final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
131 final HttpConnection conn3 = Mockito.mock(HttpConnection.class);
132
133 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 10)) {
134 pool.setMaxPerRoute("somehost", 2);
135 pool.setMaxPerRoute("otherhost", 1);
136 pool.setMaxTotal(3);
137
138 final Future<PoolEntry<String, HttpConnection>> future1 = pool.lease("somehost", null);
139 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null);
140 final Future<PoolEntry<String, HttpConnection>> future3 = pool.lease("otherhost", null);
141
142 final PoolEntry<String, HttpConnection> entry1 = future1.get();
143 Assertions.assertNotNull(entry1);
144 entry1.assignConnection(conn1);
145 final PoolEntry<String, HttpConnection> entry2 = future2.get();
146 Assertions.assertNotNull(entry2);
147 entry2.assignConnection(conn2);
148 final PoolEntry<String, HttpConnection> entry3 = future3.get();
149 Assertions.assertNotNull(entry3);
150 entry3.assignConnection(conn3);
151
152 pool.release(entry1, true);
153 pool.release(entry2, true);
154 pool.release(entry3, true);
155
156 final PoolStats totals = pool.getTotalStats();
157 Assertions.assertEquals(3, totals.getAvailable());
158 Assertions.assertEquals(0, totals.getLeased());
159 Assertions.assertEquals(0, totals.getPending());
160
161 final Future<PoolEntry<String, HttpConnection>> future4 = pool.lease("somehost", null);
162 final Future<PoolEntry<String, HttpConnection>> future5 = pool.lease("somehost", null);
163 final Future<PoolEntry<String, HttpConnection>> future6 = pool.lease("otherhost", null);
164 final Future<PoolEntry<String, HttpConnection>> future7 = pool.lease("somehost", null);
165 final Future<PoolEntry<String, HttpConnection>> future8 = pool.lease("somehost", null);
166 final Future<PoolEntry<String, HttpConnection>> future9 = pool.lease("otherhost", null);
167
168 Assertions.assertTrue(future4.isDone());
169 final PoolEntry<String, HttpConnection> entry4 = future4.get();
170 Assertions.assertNotNull(entry4);
171 Assertions.assertSame(conn2, entry4.getConnection());
172
173 Assertions.assertTrue(future5.isDone());
174 final PoolEntry<String, HttpConnection> entry5 = future5.get();
175 Assertions.assertNotNull(entry5);
176 Assertions.assertSame(conn1, entry5.getConnection());
177
178 Assertions.assertTrue(future6.isDone());
179 final PoolEntry<String, HttpConnection> entry6 = future6.get();
180 Assertions.assertNotNull(entry6);
181 Assertions.assertSame(conn3, entry6.getConnection());
182
183 Assertions.assertFalse(future7.isDone());
184 Assertions.assertFalse(future8.isDone());
185 Assertions.assertFalse(future9.isDone());
186
187 pool.release(entry4, true);
188 pool.release(entry5, false);
189 pool.release(entry6, true);
190
191 Assertions.assertTrue(future7.isDone());
192 final PoolEntry<String, HttpConnection> entry7 = future7.get();
193 Assertions.assertNotNull(entry7);
194 Assertions.assertSame(conn2, entry7.getConnection());
195
196 Assertions.assertTrue(future8.isDone());
197 final PoolEntry<String, HttpConnection> entry8 = future8.get();
198 Assertions.assertNotNull(entry8);
199 Assertions.assertNull(entry8.getConnection());
200
201 Assertions.assertTrue(future9.isDone());
202 final PoolEntry<String, HttpConnection> entry9 = future9.get();
203 Assertions.assertNotNull(entry9);
204 Assertions.assertSame(conn3, entry9.getConnection());
205 }
206 }
207
208 @Test
209 public void testConnectionRedistributionOnTotalMaxLimit() throws Exception {
210 final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
211 final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
212 final HttpConnection conn3 = Mockito.mock(HttpConnection.class);
213 final HttpConnection conn4 = Mockito.mock(HttpConnection.class);
214 final HttpConnection conn5 = Mockito.mock(HttpConnection.class);
215
216 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 10)) {
217 pool.setMaxPerRoute("somehost", 2);
218 pool.setMaxPerRoute("otherhost", 2);
219 pool.setMaxTotal(2);
220
221 final Future<PoolEntry<String, HttpConnection>> future1 = pool.lease("somehost", null);
222 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null);
223 final Future<PoolEntry<String, HttpConnection>> future3 = pool.lease("otherhost", null);
224 final Future<PoolEntry<String, HttpConnection>> future4 = pool.lease("otherhost", null);
225
226 Assertions.assertTrue(future1.isDone());
227 final PoolEntry<String, HttpConnection> entry1 = future1.get();
228 Assertions.assertNotNull(entry1);
229 Assertions.assertFalse(entry1.hasConnection());
230 entry1.assignConnection(conn1);
231 Assertions.assertTrue(future2.isDone());
232 final PoolEntry<String, HttpConnection> entry2 = future2.get();
233 Assertions.assertNotNull(entry2);
234 Assertions.assertFalse(entry2.hasConnection());
235 entry2.assignConnection(conn2);
236
237 Assertions.assertFalse(future3.isDone());
238 Assertions.assertFalse(future4.isDone());
239
240 PoolStats totals = pool.getTotalStats();
241 Assertions.assertEquals(0, totals.getAvailable());
242 Assertions.assertEquals(2, totals.getLeased());
243 Assertions.assertEquals(2, totals.getPending());
244
245 pool.release(entry1, true);
246 pool.release(entry2, true);
247
248 Assertions.assertTrue(future3.isDone());
249 final PoolEntry<String, HttpConnection> entry3 = future3.get();
250 Assertions.assertNotNull(entry3);
251 Assertions.assertFalse(entry3.hasConnection());
252 entry3.assignConnection(conn3);
253 Assertions.assertTrue(future4.isDone());
254 final PoolEntry<String, HttpConnection> entry4 = future4.get();
255 Assertions.assertNotNull(entry4);
256 Assertions.assertFalse(entry4.hasConnection());
257 entry4.assignConnection(conn4);
258
259 totals = pool.getTotalStats();
260 Assertions.assertEquals(0, totals.getAvailable());
261 Assertions.assertEquals(2, totals.getLeased());
262 Assertions.assertEquals(0, totals.getPending());
263
264 final Future<PoolEntry<String, HttpConnection>> future5 = pool.lease("somehost", null);
265 final Future<PoolEntry<String, HttpConnection>> future6 = pool.lease("otherhost", null);
266
267 pool.release(entry3, true);
268 pool.release(entry4, true);
269
270 Assertions.assertTrue(future5.isDone());
271 final PoolEntry<String, HttpConnection> entry5 = future5.get();
272 Assertions.assertNotNull(entry5);
273 Assertions.assertFalse(entry5.hasConnection());
274 entry5.assignConnection(conn5);
275 Assertions.assertTrue(future6.isDone());
276 final PoolEntry<String, HttpConnection> entry6 = future6.get();
277 Assertions.assertNotNull(entry6);
278 Assertions.assertTrue(entry6.hasConnection());
279 Assertions.assertSame(conn4, entry6.getConnection());
280
281 totals = pool.getTotalStats();
282 Assertions.assertEquals(0, totals.getAvailable());
283 Assertions.assertEquals(2, totals.getLeased());
284 Assertions.assertEquals(0, totals.getPending());
285
286 pool.release(entry5, true);
287 pool.release(entry6, true);
288
289 totals = pool.getTotalStats();
290 Assertions.assertEquals(2, totals.getAvailable());
291 Assertions.assertEquals(0, totals.getLeased());
292 Assertions.assertEquals(0, totals.getPending());}
293 }
294
295 @Test
296 public void testStatefulConnectionRedistributionOnPerRouteMaxLimit() throws Exception {
297 final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
298 final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
299
300 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 10)) {
301 pool.setMaxPerRoute("somehost", 2);
302 pool.setMaxTotal(2);
303
304 final Future<PoolEntry<String, HttpConnection>> future1 = pool.lease("somehost", null);
305 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null);
306
307 Assertions.assertTrue(future1.isDone());
308 final PoolEntry<String, HttpConnection> entry1 = future1.get();
309 entry1.assignConnection(conn1);
310 Assertions.assertNotNull(entry1);
311 Assertions.assertTrue(future2.isDone());
312 final PoolEntry<String, HttpConnection> entry2 = future2.get();
313 Assertions.assertNotNull(entry2);
314 entry2.assignConnection(conn2);
315
316 PoolStats totals = pool.getTotalStats();
317 Assertions.assertEquals(0, totals.getAvailable());
318 Assertions.assertEquals(2, totals.getLeased());
319 Assertions.assertEquals(0, totals.getPending());
320
321 entry1.updateState("some-stuff");
322 pool.release(entry1, true);
323 entry2.updateState("some-stuff");
324 pool.release(entry2, true);
325
326 final Future<PoolEntry<String, HttpConnection>> future3 = pool.lease("somehost", "some-stuff");
327 final Future<PoolEntry<String, HttpConnection>> future4 = pool.lease("somehost", "some-stuff");
328
329 Assertions.assertTrue(future1.isDone());
330 final PoolEntry<String, HttpConnection> entry3 = future3.get();
331 Assertions.assertNotNull(entry3);
332 Assertions.assertSame(conn2, entry3.getConnection());
333 Assertions.assertTrue(future4.isDone());
334 final PoolEntry<String, HttpConnection> entry4 = future4.get();
335 Assertions.assertNotNull(entry4);
336 Assertions.assertSame(conn1, entry4.getConnection());
337
338 pool.release(entry3, true);
339 pool.release(entry4, true);
340
341 totals = pool.getTotalStats();
342 Assertions.assertEquals(2, totals.getAvailable());
343 Assertions.assertEquals(0, totals.getLeased());
344 Assertions.assertEquals(0, totals.getPending());
345
346 final Future<PoolEntry<String, HttpConnection>> future5 = pool.lease("somehost", "some-other-stuff");
347
348 Assertions.assertTrue(future5.isDone());
349
350 Mockito.verify(conn2).close(CloseMode.GRACEFUL);
351 Mockito.verify(conn1, Mockito.never()).close(ArgumentMatchers.any());
352
353 totals = pool.getTotalStats();
354 Assertions.assertEquals(1, totals.getAvailable());
355 Assertions.assertEquals(1, totals.getLeased());
356 }
357 }
358
359 @Test
360 public void testCreateNewIfExpired() throws Exception {
361 final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
362
363 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 2)) {
364
365 final Future<PoolEntry<String, HttpConnection>> future1 = pool.lease("somehost", null);
366
367 Assertions.assertTrue(future1.isDone());
368 final PoolEntry<String, HttpConnection> entry1 = future1.get();
369 Assertions.assertNotNull(entry1);
370 entry1.assignConnection(conn1);
371
372 entry1.updateExpiry(TimeValue.of(1, TimeUnit.MILLISECONDS));
373 pool.release(entry1, true);
374
375 Thread.sleep(200L);
376
377 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null);
378
379 Assertions.assertTrue(future2.isDone());
380
381 Mockito.verify(conn1).close(CloseMode.GRACEFUL);
382
383 final PoolStats totals = pool.getTotalStats();
384 Assertions.assertEquals(0, totals.getAvailable());
385 Assertions.assertEquals(1, totals.getLeased());
386 Assertions.assertEquals(Collections.singleton("somehost"), pool.getRoutes());
387 final PoolStats stats = pool.getStats("somehost");
388 Assertions.assertEquals(0, stats.getAvailable());
389 Assertions.assertEquals(1, stats.getLeased());
390 }
391 }
392
393 @Test
394 public void testCloseExpired() throws Exception {
395 final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
396 final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
397
398 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 2)) {
399
400 final Future<PoolEntry<String, HttpConnection>> future1 = pool.lease("somehost", null);
401 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null);
402
403 Assertions.assertTrue(future1.isDone());
404 final PoolEntry<String, HttpConnection> entry1 = future1.get();
405 Assertions.assertNotNull(entry1);
406 entry1.assignConnection(conn1);
407 Assertions.assertTrue(future2.isDone());
408 final PoolEntry<String, HttpConnection> entry2 = future2.get();
409 Assertions.assertNotNull(entry2);
410 entry2.assignConnection(conn2);
411
412 entry1.updateExpiry(TimeValue.of(1, TimeUnit.MILLISECONDS));
413 pool.release(entry1, true);
414
415 Thread.sleep(200);
416
417 entry2.updateExpiry(TimeValue.of(1000, TimeUnit.SECONDS));
418 pool.release(entry2, true);
419
420 pool.closeExpired();
421
422 Mockito.verify(conn1).close(CloseMode.GRACEFUL);
423 Mockito.verify(conn2, Mockito.never()).close(ArgumentMatchers.any());
424
425 final PoolStats totals = pool.getTotalStats();
426 Assertions.assertEquals(1, totals.getAvailable());
427 Assertions.assertEquals(0, totals.getLeased());
428 Assertions.assertEquals(0, totals.getPending());
429 final PoolStats stats = pool.getStats("somehost");
430 Assertions.assertEquals(1, stats.getAvailable());
431 Assertions.assertEquals(0, stats.getLeased());
432 Assertions.assertEquals(0, stats.getPending());
433 }
434 }
435
436 @Test
437 public void testCloseIdle() throws Exception {
438 final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
439 final HttpConnection conn2 = Mockito.mock(HttpConnection.class);
440
441 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 2)) {
442
443 final Future<PoolEntry<String, HttpConnection>> future1 = pool.lease("somehost", null);
444 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null);
445
446 Assertions.assertTrue(future1.isDone());
447 final PoolEntry<String, HttpConnection> entry1 = future1.get();
448 Assertions.assertNotNull(entry1);
449 entry1.assignConnection(conn1);
450 Assertions.assertTrue(future2.isDone());
451 final PoolEntry<String, HttpConnection> entry2 = future2.get();
452 Assertions.assertNotNull(entry2);
453 entry2.assignConnection(conn2);
454
455 entry1.updateState(null);
456 pool.release(entry1, true);
457
458 Thread.sleep(200L);
459
460 entry2.updateState(null);
461 pool.release(entry2, true);
462
463 pool.closeIdle(TimeValue.of(50, TimeUnit.MILLISECONDS));
464
465 Mockito.verify(conn1).close(CloseMode.GRACEFUL);
466 Mockito.verify(conn2, Mockito.never()).close(ArgumentMatchers.any());
467
468 PoolStats totals = pool.getTotalStats();
469 Assertions.assertEquals(1, totals.getAvailable());
470 Assertions.assertEquals(0, totals.getLeased());
471 Assertions.assertEquals(0, totals.getPending());
472 PoolStats stats = pool.getStats("somehost");
473 Assertions.assertEquals(1, stats.getAvailable());
474 Assertions.assertEquals(0, stats.getLeased());
475 Assertions.assertEquals(0, stats.getPending());
476
477 pool.closeIdle(TimeValue.of(-1, TimeUnit.MILLISECONDS));
478
479 Mockito.verify(conn2).close(CloseMode.GRACEFUL);
480
481 totals = pool.getTotalStats();
482 Assertions.assertEquals(0, totals.getAvailable());
483 Assertions.assertEquals(0, totals.getLeased());
484 Assertions.assertEquals(0, totals.getPending());
485 stats = pool.getStats("somehost");
486 Assertions.assertEquals(0, stats.getAvailable());
487 Assertions.assertEquals(0, stats.getLeased());
488 Assertions.assertEquals(0, stats.getPending());
489 }
490 }
491
492 @Test
493 public void testLeaseRequestTimeout() throws Exception {
494 final HttpConnection conn1 = Mockito.mock(HttpConnection.class);
495
496 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(1, 1)) {
497
498 final Future<PoolEntry<String, HttpConnection>> future1 = pool.lease("somehost", null, Timeout.ofMilliseconds(0), null);
499 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null, Timeout.ofMilliseconds(0), null);
500 final Future<PoolEntry<String, HttpConnection>> future3 = pool.lease("somehost", null, Timeout.ofMilliseconds(10), null);
501
502 Assertions.assertTrue(future1.isDone());
503 final PoolEntry<String, HttpConnection> entry1 = future1.get();
504 Assertions.assertNotNull(entry1);
505 entry1.assignConnection(conn1);
506 Assertions.assertFalse(future2.isDone());
507 Assertions.assertFalse(future3.isDone());
508
509 Thread.sleep(100);
510
511 pool.validatePendingRequests();
512
513 Assertions.assertFalse(future2.isDone());
514 Assertions.assertTrue(future3.isDone());
515 }
516 }
517
518 private static class HoldInternalLockThread extends Thread {
519 private HoldInternalLockThread(final StrictConnPool<String, HttpConnection> pool, final CountDownLatch lockHeld) {
520 super(() -> {
521 pool.lease("somehost", null);
522 pool.enumLeased(object -> {
523 try {
524 lockHeld.countDown();
525 Thread.sleep(Long.MAX_VALUE);
526 } catch (final InterruptedException ignored) {
527 }
528 });
529 });
530 }
531 }
532
533 @Test
534 public void testLeaseRequestLockTimeout() throws Exception {
535 final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(1, 1);
536 final CountDownLatch lockHeld = new CountDownLatch(1);
537 final Thread holdInternalLock = new HoldInternalLockThread(pool, lockHeld);
538
539 holdInternalLock.start();
540 lockHeld.await();
541
542
543 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null, Timeout.ofMilliseconds(10), null);
544
545 final ExecutionException executionException = Assertions.assertThrows(ExecutionException.class, () ->
546 future2.get());
547 Assertions.assertTrue(executionException.getCause() instanceof DeadlineTimeoutException);
548 holdInternalLock.interrupt();
549 }
550
551 @Test
552 public void testLeaseRequestInterrupted() throws Exception {
553 final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(1, 1);
554 final CountDownLatch lockHeld = new CountDownLatch(1);
555 final Thread holdInternalLock = new HoldInternalLockThread(pool, lockHeld);
556
557 holdInternalLock.start();
558 lockHeld.await();
559
560 Thread.currentThread().interrupt();
561
562 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null, Timeout.ofMilliseconds(10), null);
563
564 Assertions.assertTrue(Thread.interrupted());
565 Assertions.assertThrows(CancellationException.class, () -> future2.get());
566 holdInternalLock.interrupt();
567 }
568
569 @Test
570 public void testLeaseRequestCanceled() throws Exception {
571 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(1, 1)) {
572
573 final Future<PoolEntry<String, HttpConnection>> future1 = pool.lease("somehost", null,
574 Timeout.ofMilliseconds(0), null);
575
576 Assertions.assertTrue(future1.isDone());
577 final PoolEntry<String, HttpConnection> entry1 = future1.get();
578 Assertions.assertNotNull(entry1);
579 entry1.assignConnection(Mockito.mock(HttpConnection.class));
580
581 final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null,
582 Timeout.ofMilliseconds(0), null);
583 future2.cancel(true);
584
585 pool.release(entry1, true);
586
587 final PoolStats totals = pool.getTotalStats();
588 Assertions.assertEquals(1, totals.getAvailable());
589 Assertions.assertEquals(0, totals.getLeased());
590 }
591 }
592
593 @Test
594 public void testGetStatsInvalid() throws Exception {
595 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 2)) {
596 Assertions.assertThrows(NullPointerException.class, () -> pool.getStats(null));
597 }
598 }
599
600 @Test
601 public void testSetMaxInvalid() throws Exception {
602 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 2)) {
603 Assertions.assertThrows(IllegalArgumentException.class, () ->
604 pool.setMaxTotal(-1));
605 Assertions.assertThrows(NullPointerException.class, () ->
606 pool.setMaxPerRoute(null, 1));
607 Assertions.assertThrows(IllegalArgumentException.class, () ->
608 pool.setDefaultMaxPerRoute(-1));
609 }
610 }
611
612 @Test
613 public void testSetMaxPerRoute() throws Exception {
614 try (final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 2)) {
615 pool.setMaxPerRoute("somehost", 1);
616 Assertions.assertEquals(1, pool.getMaxPerRoute("somehost"));
617 pool.setMaxPerRoute("somehost", 0);
618 Assertions.assertEquals(0, pool.getMaxPerRoute("somehost"));
619 pool.setMaxPerRoute("somehost", -1);
620 Assertions.assertEquals(2, pool.getMaxPerRoute("somehost"));
621 }
622 }
623
624 @Test
625 public void testShutdown() throws Exception {
626 final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 2);
627 pool.close(CloseMode.GRACEFUL);
628 Assertions.assertThrows(IllegalStateException.class, () -> pool.lease("somehost", null));
629
630 pool.release(new PoolEntry<>("somehost"), true);
631 }
632
633 }