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