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