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
28
29
30
31 package org.apache.commons.httpclient;
32
33 import java.io.IOException;
34 import java.lang.ref.WeakReference;
35 import java.net.InetAddress;
36 import java.net.Socket;
37 import java.net.UnknownHostException;
38
39 import junit.framework.Test;
40 import junit.framework.TestSuite;
41
42 import org.apache.commons.httpclient.methods.GetMethod;
43 import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
44 import org.apache.commons.httpclient.params.HttpConnectionParams;
45 import org.apache.commons.httpclient.protocol.Protocol;
46 import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
47 import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
48
49 /***
50 * Unit tests for {@link HttpConnectionManager}.
51 *
52 * @author Marc A. Saegesser
53 * @version $Id: TestHttpConnectionManager.java 155418 2005-02-26 13:01:52Z dirkv $
54 */
55 public class TestHttpConnectionManager extends TestLocalHostBase {
56
57
58 public TestHttpConnectionManager(String testName) {
59 super(testName);
60 }
61
62
63 public static void main(String args[]) {
64 String[] testCaseName = { TestHttpConnectionManager.class.getName() };
65 junit.textui.TestRunner.main(testCaseName);
66 }
67
68
69
70 public static Test suite() {
71 return new TestSuite(TestHttpConnectionManager.class);
72 }
73
74
75
76
77 /***
78 * Test that the ConnectMethod correctly releases connections when
79 * CONNECT fails.
80 */
81 public void testConnectMethodFailureRelease() throws Exception {
82
83 MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
84 mgr.getParams().setIntParameter(
85 HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
86 HttpClient client = createHttpClient(mgr);
87
88
89
90
91 client.getHostConfiguration().setProxy(getHost(), getPort());
92
93
94 client.getHostConfiguration().setHost(
95 "notARealHost",
96 1234,
97 new Protocol(
98 "https",
99 (ProtocolSocketFactory)new FakeSecureProtocolSocketFactory(),
100 443)
101 );
102
103 GetMethod get = new GetMethod("/");
104 try {
105 assertTrue(client.executeMethod(get) != 200);
106 } catch (IOException e) {
107 e.printStackTrace();
108 fail("Error executing connect: " + e);
109 }
110
111
112 try {
113 get.releaseConnection();
114 mgr.getConnectionWithTimeout(client.getHostConfiguration(), 1).releaseConnection();
115 } catch (ConnectTimeoutException e1) {
116 fail("Connection should have been available.");
117 }
118
119 get = new GetMethod("/");
120
121 try {
122 assertTrue(client.executeMethod(get) != 200);
123 } catch (IOException e) {
124 e.printStackTrace();
125 fail("Error executing connect: " + e);
126 }
127
128
129 try {
130 get.getResponseBodyAsString();
131 mgr.getConnectionWithTimeout(client.getHostConfiguration(), 1).releaseConnection();
132 } catch (ConnectTimeoutException e1) {
133 fail("Connection should have been available.");
134 }
135
136 get = new GetMethod("/");
137
138 try {
139 assertTrue(client.executeMethod(get) != 200);
140 } catch (IOException e) {
141 e.printStackTrace();
142 fail("Error executing connect: " + e);
143 }
144
145
146 try {
147 get.getResponseBodyAsStream().close();
148 mgr.getConnectionWithTimeout(client.getHostConfiguration(), 1).releaseConnection();
149 } catch (ConnectTimeoutException e) {
150 fail("Connection should have been available.");
151 } catch (IOException e) {
152 e.printStackTrace();
153 fail("Close connection failed: " + e);
154 }
155 }
156
157 public void testGetConnection() {
158 MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
159
160 HostConfiguration hostConfiguration = new HostConfiguration();
161 hostConfiguration.setHost("www.nosuchserver.com", 80, "http");
162
163
164 HttpConnection conn = mgr.getConnection(hostConfiguration);
165
166 assertEquals("Host", "www.nosuchserver.com", conn.getHost());
167 assertEquals("Port", 80, conn.getPort());
168
169 mgr.releaseConnection(conn);
170
171
172 hostConfiguration.setHost("www.nosuchserver.com", -1, "https");
173 conn = mgr.getConnection(hostConfiguration);
174
175 assertEquals("Host", "www.nosuchserver.com", conn.getHost());
176 assertEquals("Port", 443, conn.getPort());
177
178 mgr.releaseConnection(conn);
179
180
181 hostConfiguration.setHost("www.nowhere.org", 8080, "http");
182 conn = mgr.getConnection(hostConfiguration);
183
184 assertEquals("Host", "www.nowhere.org", conn.getHost());
185 assertEquals("Port", 8080, conn.getPort());
186
187 mgr.releaseConnection(conn);
188
189 }
190
191 public void testDroppedThread() throws Exception {
192
193 MultiThreadedHttpConnectionManager mthcm = new MultiThreadedHttpConnectionManager();
194 HttpClient httpClient = createHttpClient(mthcm);
195 WeakReference wr = new WeakReference(mthcm);
196
197 GetMethod method = new GetMethod("/");
198 httpClient.executeMethod(method);
199 method.releaseConnection();
200
201 mthcm = null;
202 httpClient = null;
203 method = null;
204
205 System.gc();
206
207
208
209 try {
210 Thread.sleep(1000);
211 } catch (InterruptedException e) {
212 fail("shouldn't be interrupted.");
213 }
214
215 Object connectionManager = wr.get();
216 assertNull("connectionManager should be null", connectionManager);
217 }
218
219 public void testWriteRequestReleaseConnection() {
220
221 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
222 connectionManager.getParams().setDefaultMaxConnectionsPerHost(1);
223
224 HttpClient client = createHttpClient(connectionManager);
225
226 GetMethod get = new GetMethod("/") {
227 protected boolean writeRequestBody(HttpState state, HttpConnection conn)
228 throws IOException, HttpException {
229 throw new IOException("Oh no!!");
230 }
231 };
232
233 try {
234 client.executeMethod(get);
235 fail("An exception should have occurred.");
236 } catch (HttpException e) {
237 e.printStackTrace();
238 fail("HttpException should not have occurred: " + e);
239 } catch (IOException e) {
240
241 }
242
243 try {
244 connectionManager.getConnectionWithTimeout(client.getHostConfiguration(), 1);
245 } catch (ConnectTimeoutException e) {
246 e.printStackTrace();
247 fail("Connection was not released: " + e);
248 }
249
250 }
251
252 public void testReleaseConnection() {
253
254 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
255 connectionManager.getParams().setDefaultMaxConnectionsPerHost(1);
256
257 HttpClient client = createHttpClient(connectionManager);
258
259 client.getParams().setConnectionManagerTimeout(1);
260
261 GetMethod getMethod = new GetMethod("/");
262
263 try {
264 client.executeMethod(getMethod);
265 } catch (Exception e) {
266 fail("error reading from server: " + e);
267 }
268
269 try {
270
271 client.executeMethod(getMethod);
272 fail("a httpConnection should not be available");
273 } catch (ConnectTimeoutException e) {
274 } catch (HttpException e) {
275 fail("error reading from server; " + e);
276 } catch (IOException e) {
277 e.printStackTrace();
278 fail("error reading from server; " + e);
279 }
280
281
282 getMethod.releaseConnection();
283
284 getMethod = new GetMethod("/");
285
286 try {
287
288 client.executeMethod(getMethod);
289 } catch (HttpException e) {
290 fail("httpConnection does not appear to have been released: " + e);
291 } catch (IOException e) {
292 fail("error reading from server; " + e);
293 }
294
295 }
296
297 /***
298 * Makes sure that a connection gets released after the content of the body
299 * is read.
300 */
301 public void testResponseAutoRelease() throws Exception {
302
303 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
304 connectionManager.getParams().setDefaultMaxConnectionsPerHost(1);
305
306 HttpClient client = createHttpClient(connectionManager);
307
308 client.getParams().setConnectionManagerTimeout( 1 );
309
310 GetMethod getMethod = new GetMethod("/");
311
312 try {
313 client.executeMethod(getMethod);
314 } catch (Exception e) {
315 fail("error reading from server: " + e);
316 }
317
318
319 getMethod.getResponseBody();
320
321 getMethod = new GetMethod("/");
322
323 try {
324
325 client.executeMethod(getMethod);
326 } catch (HttpException e) {
327 fail("httpConnection does not appear to have been released: " + e);
328 } catch (IOException e) {
329 fail("error reading from server; " + e);
330 }
331
332 }
333
334 /***
335 * Tests the MultiThreadedHttpConnectionManager's ability to reclaim unused
336 * connections.
337 */
338 public void testConnectionReclaiming() {
339
340 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
341 connectionManager.getParams().setDefaultMaxConnectionsPerHost(1);
342 connectionManager.getParams().setMaxTotalConnections(1);
343
344 HostConfiguration host1 = new HostConfiguration();
345 host1.setHost("host1", -1, "http");
346
347 HostConfiguration host2 = new HostConfiguration();
348 host2.setHost("host2", -1, "http");
349
350 HttpConnection connection = connectionManager.getConnection(host1);
351
352 connection.releaseConnection();
353 connection = null;
354
355 try {
356
357 connection = connectionManager.getConnectionWithTimeout(host2, 100);
358 } catch (ConnectTimeoutException e) {
359 e.printStackTrace();
360 fail("a httpConnection should have been available: " + e);
361 }
362 }
363
364 /***
365 * Tests that {@link MultiThreadedHttpConnectionManager#shutdownAll()} closes all resources
366 * and makes all connection mangers unusable.
367 */
368 public void testShutdownAll() {
369
370 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
371 connectionManager.getParams().setDefaultMaxConnectionsPerHost(1);
372 connectionManager.getParams().setMaxTotalConnections(1);
373
374 HostConfiguration host1 = new HostConfiguration();
375 host1.setHost("host1", -1, "http");
376
377
378 HttpConnection connection = connectionManager.getConnection(host1);
379
380
381 GetConnectionThread getConn = new GetConnectionThread(host1, connectionManager, 0);
382 getConn.start();
383
384 MultiThreadedHttpConnectionManager.shutdownAll();
385
386
387 connection.releaseConnection();
388 connection = null;
389
390 try {
391 getConn.join();
392 } catch (InterruptedException e) {
393 e.printStackTrace();
394 }
395
396
397 assertNull("Not connection should have been checked out", getConn.getConnection());
398 assertNotNull("There should have been an exception", getConn.getException());
399
400 try {
401 connectionManager.getConnection(host1);
402 fail("An exception should have occurred");
403 } catch (Exception e) {
404
405 }
406 }
407
408 /***
409 * Tests that {@link MultiThreadedHttpConnectionManager#shutdown()} closes all resources
410 * and makes the connection manger unusable.
411 */
412 public void testShutdown() {
413
414 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
415 connectionManager.getParams().setDefaultMaxConnectionsPerHost(1);
416 connectionManager.getParams().setMaxTotalConnections(1);
417
418 HostConfiguration host1 = new HostConfiguration();
419 host1.setHost("host1", -1, "http");
420
421
422 HttpConnection connection = connectionManager.getConnection(host1);
423
424
425 GetConnectionThread getConn = new GetConnectionThread(host1, connectionManager, 0);
426 getConn.start();
427
428 connectionManager.shutdown();
429
430
431 connection.releaseConnection();
432 connection = null;
433
434 try {
435 getConn.join();
436 } catch (InterruptedException e) {
437 e.printStackTrace();
438 }
439
440
441 assertNull("Not connection should have been checked out", getConn.getConnection());
442 assertNotNull("There should have been an exception", getConn.getException());
443
444 try {
445 connectionManager.getConnection(host1);
446 fail("An exception should have occurred");
447 } catch (Exception e) {
448
449 }
450 }
451
452 /***
453 * Tests the MultiThreadedHttpConnectionManager's ability to restrict the maximum number
454 * of connections.
455 */
456 public void testMaxConnections() {
457
458 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
459 connectionManager.getParams().setDefaultMaxConnectionsPerHost(1);
460 connectionManager.getParams().setMaxTotalConnections(2);
461
462 HostConfiguration host1 = new HostConfiguration();
463 host1.setHost("host1", -1, "http");
464
465 HostConfiguration host2 = new HostConfiguration();
466 host2.setHost("host2", -1, "http");
467
468 HttpConnection connection1 = connectionManager.getConnection(host1);
469 HttpConnection connection2 = connectionManager.getConnection(host2);
470
471 try {
472
473 connectionManager.getConnectionWithTimeout(host2, 100);
474 fail("a httpConnection should not be available");
475 } catch (ConnectTimeoutException e) {
476
477 }
478
479
480 connection2.releaseConnection();
481 connection2 = null;
482
483 try {
484
485 connection2 = connectionManager.getConnectionWithTimeout(host2, 100);
486 } catch (ConnectTimeoutException e) {
487 e.printStackTrace();
488 fail("a httpConnection should have been available: " + e);
489 }
490 }
491
492 public void testHostReusePreference() {
493
494 final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
495 connectionManager.getParams().setDefaultMaxConnectionsPerHost(1);
496 connectionManager.getParams().setMaxTotalConnections(1);
497
498 final HostConfiguration host1 = new HostConfiguration();
499 host1.setHost("host1", -1, "http");
500
501 final HostConfiguration host2 = new HostConfiguration();
502 host2.setHost("host2", -1, "http");
503
504 HttpConnection connection = connectionManager.getConnection(host1);
505
506 GetConnectionThread getHost1 = new GetConnectionThread(host1, connectionManager, 200);
507 GetConnectionThread getHost2 = new GetConnectionThread(host2, connectionManager, 200);
508
509 getHost2.start();
510 getHost1.start();
511
512
513 try {
514 Thread.sleep(100);
515 } catch (InterruptedException e1) {
516 e1.printStackTrace();
517 }
518
519
520 connection.releaseConnection();
521 connection = null;
522
523 try {
524 getHost1.join();
525 getHost2.join();
526 } catch (InterruptedException e) {
527 e.printStackTrace();
528 }
529
530 assertNotSame(
531 "Connection should have been given to someone",
532 getHost1.getConnection(),
533 getHost2.getConnection()
534 );
535 assertNotNull("Connection should have been given to host1", getHost1.getConnection());
536 assertNull("Connection should NOT have been given to host2", getHost2.getConnection());
537
538 }
539
540 public void testMaxConnectionsPerServer() {
541
542 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
543 connectionManager.getParams().setDefaultMaxConnectionsPerHost(1);
544
545 HttpClient client = createHttpClient(connectionManager);
546
547 client.getParams().setConnectionManagerTimeout( 1 );
548
549 GetMethod getMethod = new GetMethod("/");
550
551 try {
552 client.executeMethod(getMethod);
553 } catch (Exception e) {
554 fail("error reading from server: " + e);
555 }
556
557 GetMethod getMethod2 = new GetMethod("/");
558
559 try {
560
561 client.executeMethod(getMethod2);
562 fail("a httpConnection should not be available");
563 } catch (ConnectTimeoutException e) {
564 } catch (HttpException e) {
565 fail("error reading from server; " + e);
566 } catch (IOException e) {
567 fail("error reading from server; " + e);
568 }
569
570 }
571
572 public void testDeleteClosedConnections() {
573
574 MultiThreadedHttpConnectionManager manager = new MultiThreadedHttpConnectionManager();
575
576 HostConfiguration hostConfig = new HostConfiguration();
577
578 configureHostConfiguration(hostConfig);
579
580 HttpConnection conn = manager.getConnection(hostConfig);
581
582 assertEquals("connectionsInPool", manager.getConnectionsInPool(), 1);
583 assertEquals("connectionsInPool(host)", manager.getConnectionsInPool(hostConfig), 1);
584
585 conn.close();
586 conn.releaseConnection();
587
588 assertEquals("connectionsInPool", manager.getConnectionsInPool(), 1);
589 assertEquals("connectionsInPool(host)", manager.getConnectionsInPool(hostConfig), 1);
590
591 manager.deleteClosedConnections();
592
593 assertEquals("connectionsInPool", manager.getConnectionsInPool(), 0);
594 assertEquals("connectionsInPool(host)", manager.getConnectionsInPool(hostConfig), 0);
595 }
596
597 public void testReclaimUnusedConnection() {
598
599 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
600 connectionManager.getParams().setIntParameter(
601 HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
602
603 HttpClient client = createHttpClient(connectionManager);
604
605 client.getParams().setConnectionManagerTimeout( 30000 );
606
607 GetMethod getMethod = new GetMethod("/");
608
609 try {
610 client.executeMethod(getMethod);
611 } catch (Exception e) {
612 fail("error reading from server: " + e);
613 }
614
615 getMethod = new GetMethod("/");
616
617 Runtime.getRuntime().gc();
618
619 try {
620
621
622 client.executeMethod(getMethod);
623 } catch (HttpException e) {
624 fail("httpConnection does not appear to have been reclaimed by the GC: " + e);
625 } catch (IOException e) {
626 fail("error reading from server; " + e);
627 }
628
629 }
630
631 public void testGetFromMultipleThreads() {
632
633 HttpClient client = createHttpClient(new MultiThreadedHttpConnectionManager());
634 ExecuteMethodThread[] threads = new ExecuteMethodThread[10];
635
636 for (int i = 0; i < threads.length; i++) {
637 GetMethod method = new GetMethod("/");
638 method.setFollowRedirects(true);
639
640 threads[i] = new ExecuteMethodThread(method, client);
641 threads[i].start();
642 }
643
644 for (int i = 0; i < threads.length; i++) {
645 try {
646
647
648 threads[i].join(10000);
649 } catch (InterruptedException e) {
650 }
651
652 Exception e = threads[i].getException();
653 if (e != null) {
654 fail("An error occured in the get: " + e);
655 }
656
657 assertEquals(threads[i].getMethod().getStatusCode(), HttpStatus.SC_OK);
658 }
659 }
660
661 public void testTimeout() {
662 MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
663 mgr.getParams().setDefaultMaxConnectionsPerHost(2);
664
665 try{
666 HostConfiguration hostConfig = new HostConfiguration();
667 hostConfig.setHost("www.nosuchserver.com", 80, "http");
668
669 HttpConnection conn1 = mgr.getConnection(hostConfig);
670 HttpConnection conn2 = mgr.getConnection(hostConfig);
671
672 HttpConnection conn3 = mgr.getConnectionWithTimeout(hostConfig, 1000);
673 fail("Expected an HttpException.");
674
675 }catch(ConnectTimeoutException e){
676
677 }
678 }
679
680 static class FakeSecureProtocolSocketFactory implements SecureProtocolSocketFactory {
681
682 public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
683 throws IOException, UnknownHostException {
684 throw new IllegalStateException("createSocket() should never have been called.");
685 }
686
687 public Socket createSocket(String host, int port)
688 throws IOException, UnknownHostException {
689 throw new IllegalStateException("createSocket() should never have been called.");
690 }
691
692 public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort)
693 throws IOException, UnknownHostException {
694 throw new IllegalStateException("createSocket() should never have been called.");
695 }
696
697 public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort,
698 HttpConnectionParams params)
699 throws IOException, UnknownHostException {
700 throw new IllegalStateException("createSocket() should never have been called.");
701 }
702 }
703
704 static class GetConnectionThread extends Thread {
705
706 private HostConfiguration hostConfiguration;
707 private MultiThreadedHttpConnectionManager connectionManager;
708 private HttpConnection connection;
709 private long timeout;
710 private Exception exception;
711
712 public GetConnectionThread(
713 HostConfiguration hostConfiguration,
714 MultiThreadedHttpConnectionManager connectionManager,
715 long timeout
716 ) {
717 this.hostConfiguration = hostConfiguration;
718 this.connectionManager = connectionManager;
719 this.timeout = timeout;
720 }
721
722 public void run() {
723 try {
724 connection = connectionManager.getConnectionWithTimeout(hostConfiguration, timeout);
725 } catch (Exception e) {
726 this.exception = e;
727 }
728 }
729
730 public Exception getException() {
731 return exception;
732 }
733
734 public HttpConnection getConnection() {
735 return connection;
736 }
737
738 }
739
740 }
741